티스토리 뷰
반응형
리플렉션 ( java.io.reflect )
- 리플렉션 기능을 이용하면 임의의 클래스에 접근할 수 있다.
- 자바 클래스파일 정보는 컴파일되면 클래스파일로 변환되어 메모리의 Static 영역에 위치
- Static 영역의 정보는 언제든지 접근할 수 있기 때문에 클래스의 이름만 알면 정보들을 가져올 수 있음
- Class 객체가 주어지면 그 클래스의 생성자, 메섣, 필드에 해당하는 인스턴스를 가져올 수 있음
- 인스턴스들로 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있음
- 인스턴스를 이용하여 각각에 연결된 생성자, 메서드, 필드 조작 가능 (해당 클래스 인스턴스 생성, 메서드 호출, 필드 접근 등 가능)
// 클래스 얻기 Class<?> class = Class.forName(); //생성자 얻기 Constructor<?> constructor = class.getDeclaredConstructor(); // 클래스 인스턴스 만들기 constructor.newInstance();
리플렉션의 단점
- 컴파일타임 타입 검사가 주는 이점을 누릴 수 없음
- 예외 검사도 마찬가지
- 리플렉션으로 존재하지 않는 or 접근할 수 없는 메서드를 호출하려한다면 런타임 오류 발생
- 코드가 지저분하고 장황해짐
- 성능이 떨어짐
→ 리플렉션은 아주 제한된 형태로만 사용해야 단점을 피하고 이점만 취할 수 있다.
컴파일타임에 이용할 수 없는 클래스를 사용해야만 하는 경우라면 리플렉션은 인스턴스 생성에만 쓰고 이렇게 만든 인스턴스는 인터페이스나 상위 클래스를 참조해 사용하자.
리플렉션을 이용한 인스턴스 생성
public static void main(String[] args) {
Class<? extends Set<String>> cl = null;
try {
// 여기서 args[0] 의 인자에 의해 클래스가 결정된다.
// args[0] 이 무엇인지에 따라 동작이 달라진다.
cl = (Class<? extends Set<String>>) Class.forName(args[0]);
} catch (ClassNotFoundException e) {
fatalError("클래스를 찾을 수 없습니다 !!");
}
Constructor<? extends Set<String>> cons = null;
try {
cons = cl.getConstructor();
} catch (NoSuchMethodException e) {
fatalError("매개변수없는 생성자가 없습니다 !!");
}
Set<String> s = null;
try {
s = cons.newInstance();
} catch (IllegalAccessException e) {
fatalError("생성자에 접근할 수 없습니다.");
} catch (InstantiationException e) {
fatalError("클래스를 인스턴스화할 수 없습니다.");
} catch (InvocationTargetException e) {
fatalError("생성자가 예외를 던졌습니다." + e.getCause());
} catch (ClassCastException e) {
fatalError("Set 을 구현하지 않은 클래스입니다.");
}
s.addAll(Arrays.asList(args).subList(1, args.length));
System.out.println(s);
}
위 코드로 리플렉션 단점 두가지를 알 수 있다.
- 일반적으로 생성했으면 컴파일타임에 잡을 수 있는 다수의 예외를 런타임에서야 잡을 수 있다.
- 일반적으로 생성했으면 생성자 호출 한줄로 끝날 인스턴스 생성을 여러줄 작성해야한다.
리플렉션이 사용되는 곳
런타임에 존재하지 않을 수도 있는 다르클래스, 메서드, 필드와의 의존성을 관리할 때 적합하다.
주로, 코드 분석 도구, 의존관계 주입 프레임워크에서 많이 사용된다. (Spring)
일반 개발자는 보통 어노테이션과 리플렉션 조합으로 원하는 로직을 만드는 경우에 사용한다.
결론
리플렉션은 복잡한 특수 시스템을 개발할때 필요한 강력한 기능이지만 단점도 많다.
컴파일타임에는 알 수 없는 클래스를 사용해야한다면 리플렉션을 사용해야할 것이다.
그러나 되도록 객체 생성에만 사용하고 생성한 객체를 이용할때는 적절한 인터페이스나 컴파일타임에 알 수 있는 상위클래스로 형변환하여 사용하라.
반응형
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] 67.최적화는 신중히 하라 (0) | 2022.04.12 |
---|---|
[Effective Java] 66.네이티브 메서드는 신중히 사용하라 (0) | 2022.04.12 |
[Effective Java] 64.객체는 인터페이스를 사용해 참조하라 (0) | 2022.04.12 |
[Effective Java] 63.문자열 연결은 느리니 주의하라 (0) | 2022.04.08 |
[Effective Java] 62.다른 타입이 적절하다면 문자열 사용을 피하라 (0) | 2022.04.08 |
댓글