Part2 - 객체지향 프로그래밍(2)
Interface
인터페이스의 요소
- 추상메소드
- 상수
- 디폴트 메소드
: 인터페이스에서 선언만 되어있는것이 아니라 구현부도 있는 메소드. defualt키워드를 붙여서 정의하고, 해당 인터페이스를 구현하는 클래스에서 재정의 가능 (java8) - 정적 메소드
: 인스턴스생성과 상관없이 인터페이스 타입으로 호출하는 메소드 (java8) - 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에서 재정의 할 수 있는 메소드는 다음과 같다.
int hashCode();
int equals();
Object clone();
String toString();
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 클래스 가져오기
-
String s = new String(); Class c = s.getClass();
Class c = String.Class;
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 메소드
-
- 동적로딩?
- 컴파일 시 데이터 타입이 모두 바인딩되어 자료형이 로딩되는 것이 아니라, 실행중에 데이터 타입을 알고
바인딩 되는 방식
실행시에 로딩되므로 경우에 따라 다른 타입의 클래스를 사용할 수 있다. 컴파일 타임에 체크할 수 없으므로 해당 문자열에 대한 클래스가 없는 경우 예외가 발생할 수 있다.