Reflection은 자바에서 이미 로딩이 완료된 클래스에서 또는 다른 클래스를 동적으로 로딩하여 구체적인 타입을 알지 못하더라도 생성자, 멤버 필드, 그리고 멤버 메소드를 사용할 수 있는 기법이다. 객체를 통해서 클래스의 패키지 정보, 접근 지정자, 부모 클래스, 어노테이션 등을 얻을 수 있다. 즉, 핵심은 컴파일 타임이 아니라 런타임에 동적으로 특정 클래스의 정보를 객체화하여 분석 및 추출해낼 수 있는 프로그래밍 기법이다.
public class MyClass {
private String field;
public MyClass() {}
public void setField(String field) {
this.field = field;
}
public String getField() {
return field;
}
}
public class ReflectionExample {
public static void main(String[] args) {
try {
// 클래스 로딩
Class<?> clazz = Class.forName("MyClass");
// 클래스 이름 출력
System.out.println("Class Name: " + clazz.getName());
// 생성자 정보 출력
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor.getName());
}
// 필드 정보 출력
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("Field: " + field.getName());
}
// 메소드 정보 출력
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("MyClass");
Object instance = clazz.newInstance();
// 필드에 접근하여 값 설정
Field field = clazz.getDeclaredField("field");
field.setAccessible(true);
field.set(instance, "Hello, Reflection!");
// 메소드를 통해 값 가져오기
Method getFieldMethod = clazz.getMethod("getField");
String fieldValue = (String) getFieldMethod.invoke(instance);
System.out.println("Field Value: " + fieldValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Reflection은 강력한 기능을 제공하지만, 잘못 사용하면 성능 저하와 보안 문제를 일으킬 수 있다. 따라서 Reflection을 사용할 때는 필요한 경우에만 신중하게 사용해야 한다. 특히, 성능이 중요한 부분이나 보안에 민감한 부분에서는 가능한 사용을 피하는 것이 좋다. 하지만 적절히 사용한다면 매우 유연하고 강력한 코드를 작성할 수 있는 도구가 될 수 있다.