Interface

인터페이스의 요소

  1. 추상메소드
  2. 상수
  3. 디폴트 메소드
    : 인터페이스에서 선언만 되어있는것이 아니라 구현부도 있는 메소드. defualt키워드를 붙여서 정의하고, 해당 인터페이스를 구현하는 클래스에서 재정의 가능 (java8)
  4. 정적 메소드
    : 인스턴스생성과 상관없이 인터페이스 타입으로 호출하는 메소드 (java8)
  5. private 메소드
    : 인터페이스 내에서 사용하기 위해 구현한 메소드, 재정의 불가 (java9)
public interface Interface{ // 1) 인터페이스에 선언된 변수
  double PI = 3.14;

  int method(int param1, int param2); //2) 인터페이스에 선언된 메소드
}

인터페이스에서 선언된 변수는 컴파일 과정에서 public static final 이 앞에 붙으면서 상수로 변환된다.

인터페이스에서 선언된 메소드는 컴파일과정에서 추상 메소드로 변환된다. -> 인터페이스를 구현하는 클래스는 해당 추상메소드를 구현하는것과 같다.

타입 상속과 형 변환

Interface interface = new ChildInterface();

인터페이스를 구현한 클래스는 인터페이스 타입으로 변수를 선언하여 인스턴스 생성가능(타입상속이라고도 함)

인터페이스로 갖는 다형성

ex) JDBC의 Connection interface

ex) interface를 활용한 strategy-pattern

위 예시와 같이, 인터페이스는 구현해야하는 메소드를 미리 정의해 둠으로써 개발의 설계를 할 때 청사진을 그리 는 역할을 하게 된다.

그리고 각 구현클래스마다 구현방식을 다르게 할 수 있으므로 객체지향 프로그래밍의 다형성을 나타내는 것이 인터 페이스이다.

Object class

모든 클래스의 최상의 클래스인 java.lang.Object클래스
(컴파일러가 클래스에 extends Object를 자동으로 붙여 컴파일함)
모든 클래스는 Object클래스를 상속받으며, Object클래스의 메소드를 사용할 수 있고, 일부 메소드들은 재정의 할 수 있다.

java8에서 재정의 할 수 있는 메소드는 다음과 같다.

  1. int hashCode();
  2. int equals();
  3. Object clone();
  4. String toString();
  5. void finalize();

toString()

어떤클래스의 인스턴스를 println함수로 콘솔에 찍어보면 object.클래스이름@메모리주소 와 같이 나오게 된다.

  • toString 메소드 원형
    getClass().getName() + '@' + Integer.toHexString(hashCode())

그런데 자바에서 제공하는 String타입 인스턴스는 그렇지 않다.

그 이유는 String클래스의 인스턴스를 만들어서 println할 때 toString()메소드가 다르게 정의 되어 있기 때문이다.

만약 어떤 클래스의 인스턴스에 대한정보를 바로 콘솔로 찍어서 보고 싶다면 toString을 재정의해서 println 함수로 찍어보면 된다.

equals()

두 객체의 동일함을 논리적으로 재정의 할 수 있음
물리적 동일함 : 같은 주소
논리적 동일함 : 같은 값

메모리상의 주소는 다르지만 같은 객체라고 처리하고 싶을 때 그 조건을 equals메소드를 재정의 해서 처리한다.

hashCode()

hashCode() : 인스턴스가 저장된 가상머신의 주소를 10진수로 반환 즉 hashCode()가 같으면 물리적인 동일함을 갖는다는 의미이다.
보통 equals를 재정의할 때 객체를 비교할 어떤 고유값을 반환하도록 hashCode도 같이 재정의한다.

실제 메모리 주소를 알고 싶을때에는 System.out.println(System.identityHashCode(인스턴스)); 로 찍어보면 알 수 있다.

clone()

객체의 복사본을 만든다. 기본 틀(prototype)으로부터 같은 속성값을 가진 객체의 복사본을 생성할 수 있다.
객체지향 프로그래밍의 정보은닉에 위배될 가능성이 있으므로 복제할 객체는 cloneable인터페이스를 명시해야 한다.

class SomeClass extends Cloneable{

}

이 함수는 보통 재정의해서 쓰지는 않는다.

finalize()

직접 호출되는 메소드가 아니고, 객체가 힙 메모리에서 해제될 때 garbage Collector에서 수행되는 메소드이다.

Class class

자바의 모든 클래스와 인터페이스는 컴파일 후 .class파일로 생성되는데 이 파일에는 객체의 정보가 포함되어 있다. Class 클래스는 컴파일된 .class파일에서 객체의 정보를 가져올 수 있다.

Class 클래스 가져오기

  1.   String s = new String();
      Class c = s.getClass();
    
  2. Class c = String.Class;
  3. Class c = Class.forName("java.lang.String"); 동적로딩

reflection 프로그래밍

Class 클래스로부터 객체의 정보를 가져와서 프로그래밍 하는 방식
로컬에 객체가 없고 자료형을 알 수 없는 경우 유용한 프로그래밍
java.lang.reflect 패키지에 있는 클래스를 활용

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

//psvm
Class c = Class.forName("java.lang.String");
Constructor[] cons = c3.getConstructors();
for(Constructor con : cons){
  System.out.println(con); //String 클래스의 생성자를 모두 볼 수 있다.
}

Method[] methods = c.getMethods();
for(Method method : methods){
  System.out.println(method); //String 클래스의 메소드를 모두 볼 수 있다.
}

newInstance() 메소드

  • 객체를 생성해준다.
  • 디폴트 생성자로 생성한다.
Person person = (Person)c.newInstance();

이 Person객체의 name을 파라미터로 줘서 생성하는 생성자가 있고 그 생성자를 이용하려면 다음과 같이 한다.

Class[] parameterTypes = {String.class}; //String하나를 파리미터로 받는 생성자라는 정보를 준다.
Constructor cons = c.getConstructor(parameterTypes);

Object[] initargs = {"김유신"};
Person personKim = (Person)cons.newInstance(initargs); //김유신이름의 personKim 인스턴스 생성

forName() 메소드와 동적 로딩

  • Class 클래스의 static 메소드
  • 동적로딩?
    컴파일 시 데이터 타입이 모두 바인딩되어 자료형이 로딩되는 것이 아니라, 실행중에 데이터 타입을 알고 바인딩 되는 방식
    실행시에 로딩되므로 경우에 따라 다른 타입의 클래스를 사용할 수 있다. 컴파일 타임에 체크할 수 없으므로 해당 문자열에 대한 클래스가 없는 경우 예외가 발생할 수 있다.