아이템65 | 리플렉션보다는 인터페이스를 사용하라
프로그램에서 임의의 클래스에 접근 가능
Constructor, Method, Field 인스턴스를 통해 실제 생성자, 메서드, 필드를 조작 가능
컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다.
존재하지 않는 메서드를 호출하려고 하면 런타임에서 오류 발생
리플렉션을 이용하면 코드가 지저분하고 장황해진다.
성능이 떨어진다
아주 제한된 형태로만 사용하자
인스턴스 생성 시에만 쓰고, 만든 인스턴스는 인터페이스나 상위 클래스로 참조하여 사용하자
public interface Fruit {
void setName (String name );
void printName ();
}
public class Apple implements Fruit {
private String name ;
@ Override
public void printName () {
System .out .println (name + "은 사과입니다." );
}
@ Override
public void setName (String name ) {
this .name = name ;
}
}
public class Banana implements Fruit {
private String name ;
@ Override
public void printName () {
System .out .println (name + "은 바나나입니다." );
}
@ Override
public void setName (String name ) {
this .name = name ;
}
}
public class Main {
public static void main (String [] args ) throws ClassNotFoundException {
Class <? extends Fruit > fruit = null ;
try {
fruit = (Class <? extends Fruit >) Class .forName (args [0 ]);
} catch (ClassNotFoundException e ) {
System .err .println ("클래스가 없습니다." );
System .exit (1 );
}
Constructor <? extends Fruit > fruitConstructor = null ;
try {
fruitConstructor = fruit .getDeclaredConstructor ();
} catch (NoSuchMethodException e ) {
e .printStackTrace ();
}
Fruit apple = null ;
try {
apple = fruitConstructor .newInstance (); // new Backend() or new Frontend()
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e ) {
System .err .println ("잘못된 요청입니다." );
}
apple .setName (args [1 ]);
apple .printName ();
}
}
복잡한 특수 시스템을 개발할 때 필요한 강력한 기능
단점이 많기 때문에 꼭 필요한 상황에서 되도록 객체 생성에만 사용하자