You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
이 인스턴스들을 통해 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있고, 실제 생성자, 메서드, 필드를 조작할 수 있다
컴파일 당시 존재하지 않던 클래스도 이용할 수 있다
예를 들어 Method.invoke는 어떤 클래스의 어떤 객체가 가진 어떤 메서드라도 호출할 수 있게 해준다.
하지만 다음과 같은 단점도 있다.
컴파일타임 타입 검사나 예외 검사가 주는 이점을 누릴 수 없다.
코드가 지저분하고 장황해진다.
성능이 떨어진다. 리플렉션을 통한 메서드 호출은 일반 메서드 호출보다 훨씬 느리다.
리플렉션은 제한된 형태로 사용하자
컴파일타임에 이용할 수 없는 클래스를 사용해야하는 프로그램이라도 적절한 인서페이스나 상위 클래스를 이용할 수는 있다.
그러므로, 이런 경우엔 리플렉션은 인스턴스 생성에만 쓰고, 만든 인스턴스는 인터페이스나 상위 클래스로 참조해 사용하자.
예시) 리플렉션의 단점 - Set 인터페이스의 인스턴스 생성
인수들의 출력 순서는 첫번째 인수로 지정한 클래스에 따라 달라진다. (java.util.HashSet: 무작위, java.util.TreeSet: 알파벳 순서)
publicstaticvoidmain(String[] args) {
// 클래스 이름을 Class 객체로 변환Class<? extendsSet<String>> cl = null;
try {
cl = (Class<? extendsSet<String>>) Class.forName(args[0]);
// 정확한 클래스는 명령줄의 첫번째 인수로 확정한다. 비검사 형변환!
} catch (ClassNotFoundExceptione) {
fatalError("클래스를 찾을 수 없습니다.");
}
// 생성자를 얻는다.Constructor<? extendsSet<String>> cons = null;
try {
cons = cl.getDeclaredConstructor();
} catch (NoSuchMethodExceptione) {
fatalError("매개변수 없는 생성자를 찾을 수 없습니다.");
}
// 집합의 인스턴스를 만든다.Set<String> s = null;
try {
s = cons.newInstance();
} catch (InvocationTargetExceptione) {
fatalError("생성자에 접근할 수 없습니다.");
} catch (InstantiationExceptione) {
fatalError("클래스를 인스턴스화할 수 없습니다.");
} catch (ClassCastExceptione) {
fatalError("Set을 구현하지 않은 클래스입니다.");
} catch (IllegalAccessExceptione) {
thrownewRuntimeException(e);
}
// 생성한 집합을 사용한다. 생성한 집합에 두번째 이후의 인수들을 추가한 다음 화면에 출력한다.s.addAll(Arrays.asList(args).subList(1, args.length));
System.out.println(s);
}
privatestaticvoidfatalError(Stringmsg) {
System.err.println(msg);
System.exit(1);
}
예시를 통해 리플렉션의 단점을 볼 수 있다.
런타임에 6가지의 예외를 던질 수 있다.
인스턴스를 리플렉션 없이 생성했다면 컴파일타임에 잡을 수 있는 예외들이다.
클래스 이름만으로 인스턴스를 생성하기 위해 25줄이나 되는 코드를 작성했다. 리플렉션이 아니라면 생성자 호출 한 줄로 끝났을 일이다.
리플렉션 예외 각각을 잡는 대신 모든 리플렉션 예외의 상위 클래스인 ReflectiveOperationException을 잡도록 하여 코드 길이를 줄일 수 있다.
런타임에 존재하지 않을 수 있는 다른 클래스, 메서드, 필드와의 의존성을 관리할 때 적합
리플렉션은 버전이 여러 개 존재하는 외부 패키지를 다룰 때 유용하다.
가장 오래된 버젼(최소한의 환경)만 지원하도록 컴파일 한 후, 이후 버젼의 클래스와 메서드는 리플렉션으로 접근하는 방식이다.
이런 경우 접근하려는 클래스나 메서드가 런타임에 존재하지 않을 수 있으므로 대체 수단을 이용하거나 기능을 줄여 동작하는 등의 조치를 취해야한다.
핵심 정리
리플렉션은 알 수 없는 클래스를 사용하는 프로그램을 작성할 때 등 복잡한 특수 시스템을 개발할 때 필요한 강력한 기능이지만 단점도 많다.
되도록 객체 생성에만 사용하고,생성한 객체를 이용할 때에는 적절한 인터페이스나 컴파일타임에 알 수 있는 상위 클래스로 형변환해 사용해야한다.
The text was updated successfully, but these errors were encountered:
[ Item65 ] 리플렉션보다는 인터페이스를 사용하라
리플렉션 기능 (java.lang.reflect)
리플렉션 기능을 사용하면 프로그램에서 임의의 클래스에 접근할 수 있다.
예를 들어 Method.invoke는 어떤 클래스의 어떤 객체가 가진 어떤 메서드라도 호출할 수 있게 해준다.
하지만 다음과 같은 단점도 있다.
리플렉션은 제한된 형태로 사용하자
컴파일타임에 이용할 수 없는 클래스를 사용해야하는 프로그램이라도 적절한 인서페이스나 상위 클래스를 이용할 수는 있다.
그러므로, 이런 경우엔 리플렉션은 인스턴스 생성에만 쓰고, 만든 인스턴스는 인터페이스나 상위 클래스로 참조해 사용하자.
예시) 리플렉션의 단점 - Set 인터페이스의 인스턴스 생성
예시를 통해 리플렉션의 단점을 볼 수 있다.
런타임에 6가지의 예외를 던질 수 있다.
인스턴스를 리플렉션 없이 생성했다면 컴파일타임에 잡을 수 있는 예외들이다.
클래스 이름만으로 인스턴스를 생성하기 위해 25줄이나 되는 코드를 작성했다. 리플렉션이 아니라면 생성자 호출 한 줄로 끝났을 일이다.
리플렉션 예외 각각을 잡는 대신 모든 리플렉션 예외의 상위 클래스인 ReflectiveOperationException을 잡도록 하여 코드 길이를 줄일 수 있다.
런타임에 존재하지 않을 수 있는 다른 클래스, 메서드, 필드와의 의존성을 관리할 때 적합
리플렉션은 버전이 여러 개 존재하는 외부 패키지를 다룰 때 유용하다.
가장 오래된 버젼(최소한의 환경)만 지원하도록 컴파일 한 후, 이후 버젼의 클래스와 메서드는 리플렉션으로 접근하는 방식이다.
이런 경우 접근하려는 클래스나 메서드가 런타임에 존재하지 않을 수 있으므로 대체 수단을 이용하거나 기능을 줄여 동작하는 등의 조치를 취해야한다.
핵심 정리
The text was updated successfully, but these errors were encountered: