리플렉션이란?
Reflection allows us to inspect or/and modify runtime attributes of classes, interfaces, fields, and methods. This particularly comes in handy when we don't know their names at compile time.
Additionally, we can instantiate new objects, invoke methods, and get or set field values using reflection.
클래스에 대한 메타 정보로 런타임시 동적 프로그래밍을 하는 개념인 것 같다.
동적 프로그래밍 하기 위한 객체의 정보에 접근 하기 위해서는 Class 클래스가 사용되는데
클래스를 사용(조회)하기 위해 3가지 방법이 존재한다.
1. 직접 선언
Class<Person> personClass = Person.class;
2. 인스턴스를 이용한 getClass()
Person person = new Person();
Class<? extends Person> personInstance = person.getClass();
3. Class.forName()
Class<? extends Person> personClass = Class.forName("org.example.Person");
그리고 아래처럼 오브젝트의 필드에 우선 접근해 보고 다음 예제에서 함수나 필드를 추가하는
조작을 해보자. 리플렉션이 사용된다.
[간단 예시 - 필드 접근]
public class Person {
private String name;
private int age;
}
private List<String> getFieldName(Field[] fields) {
List<String> fieldNames = new ArrayList<>();
for(Field field : fields)
fieldNames.add(field.getName());
return fieldNames;
}
@Test
public void
givenObject_whenGetsFieldNameAtRuntime_thenCoorect() {
Object person = new Person();
Field[] fields = person.getClass().getDeclaredFields();
List<String> actualFieldNames = getFieldName(fields);
Assertions.assertTrue(Arrays.asList("name", "age")
.containsAll(actualFieldNames));
}
[런타임시 동작하는 예제]
java.lang.reflect.Array 는
Array 클래스는 Java 배열을 동적으로 작성해 액세스하기 위한 static 메서드를 제공한다.
http://cris.joongbu.ac.kr/course/java/api/java/lang/reflect/Array.html - 설명
http://tutorials.jenkov.com/java-reflection/arrays.html#Array - 가이드
리플렉션 사용시 주의 할 것
- 지나친 사용은 성능 이슈 야기, 반드시 필요한 경우에만 사용
- 컴파일 타임에 확인되지 않고 런타임 시에만 발생하는 문제를 만들 가능성이 있음 (객체를 조작하는 것 이기 때문)
- 접근 지시자 무시할 수 있다. (조작 가능 하기 때문)
스프링
- 의존성 주입
- MVC 뷰에서 넘어온 데이터를 객체에 바인딩 할 때
하이버 네이트
- @Entity 클래스에 Setter 가 없다면 리플렉션을 사용
JUnit
- Junit frame 에서 사용할 ReflectionUtil
다이나믹 프록시
- 리플렉션의 일부이다.
참고
자바 리플렉션 가이드 https://www.baeldung.com/java-reflection
https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html