📂 목차
📚 본문
Reflect 패키지
자바가 지원하는 문법에 대한 정보들을 제공하고 조작할 수 있는 패키지이며, 클래스와 객체에 대한 반사적 정보를 얻기 위한 클래스와 인터페이스를 제공하는 패키지이다. 여기서 일어나는 대부분은 Checked Exception
이고, 그만큼 컴파일러 단에서 예외처리를 잘 해주어야 한다.
자주 사용되는 것들만 보자.
Class
Class<T>
: 클래스의 메타데이터를 담으며,Class.forName("패키지.클래스명")
또는obj.getClass()
로 얻을 수 있다.AccessibleObject
- Field, Method 및 Constructor 객체의 기본 클래스Field
: 클래스의 멤버 변수 정보를 다룬다. 클래스에서getDeclaredFields()
,getField("name")
메서드를 통해Field[]
를 얻을 수 있다.Method
: 클래스의 메서드 정보를 다루며, 클래스에서getDeclaredMethods()
로 배열을 가져올 수 있고,invoke()
로 실행을 할 수 있다.Constructor<T>
: 클래스의 생성자 정보Modifier
: public, private, static 등의 접근 제어자/수정자 정보를 확인한다.Array
: 리플렉션 기반의 배열 생성과 조작을 담당한다.Parameter
- 메서드 매개변수에 대한 정보
Interface
Type
- Java 프로그래밍 언어의 모든 유형에 대한 공통 부모 인터페이스WhildCardType
- ? 를 의미GenericDeclaration
- 타입형을 지칭하는 공통 인터페이스- …
Reflect 를 활용한 클래스 정보 조회
Class<?> clazz = Class.forName("java.util.ArrayList");
System.out.println("클래스 이름: " + clazz.getName());
이때 ClassNotFoundException
이 일어날 수 있다.
Reflect 를 활용한 필드 접근 및 조작
import java.lang.reflect.*;
class Exam {
private static int size = 100;
public int getSize() {
return size;
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("Exam");
Object examInstance = clazz.getDeclaredConstructor().newInstance();
System.out.println("클래스 이름: " + clazz.getName());
Field field = clazz.getDeclaredField("size");
field.setAccessible(true); // private 접근 허용
field.set(examInstance, 1);
Exam exam = new Exam();
System.out.println(exam.getSize());
}
}
굳이 private 을 위와 같이 접근해서 쓰지는 말자.
Reflect 를 활용한 인스턴스 생성
Class clazz = Class.forName("클래스풀네임");
// Java 9 이후 권장 방법
Object obj = clazz.getDeclaredConstructor().newInstance();
// 또는 매개변수가 있는 생성자의 경우
Object obj2 = clazz.getDeclaredConstructor(String.class, int.class).newInstance("값", 10);
리플렉트를 사용해야 할 경우
주로 정적(compile-time)
으로 타입을 확정하기 어려운 상황에서 동적으로 클래스/메서드/필드에 접근해야 할 때 활용되고, 의존성 주입, 테스트 코드에서 JUnit
등의 @Test 에서도 내부적으로 이를 사용한다. 또한 어노테이션, 동적 프록시 생성 등에서도 사용하게 된다.
물론 reflect 가 캡슐화를 깨뜨리는 API를 제공하고, 직접 호출보다 성능이 더 느리지만, 코딩 시점에서 정해지는 정적 타입 언어에 동적 성격을 부여할 수 있기 때문에 더 이상 자바로 처리하기 힘든 타입 바인딩에 대해 해결할 수 있는 중요한 수단이 되겠다.