Reflection?
- Java.lang.reflection에 있는 라이브러리 기능
- Class를 컴파일 단계 에 올리지 않고, 런타임 때 클래스를 동적으로 로딩하기 위해서 사용된다!
- 코드 단으로 객체(Class)에 담겨진 이름과, 모든 메서드 이름을 알 수 있다!!
- 따라서 쉬운 방식으로 메서드를 호출할 수 있다!
간단한 사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public static void main(String[] args) {
try {
Class c = Class.forName("java.util.ArrayList");
Method[] m = c.getDeclaredMethods();
Field[] f = c.getDeclaredFields();
System.out.println(c.toString() + "\n");
for (Method method : m) {
System.out.println(method.toString());
}
System.out.println();
for (Field field : f) {
System.out.println(field.toString());
}
} catch (ClassNotFoundException e) {
System.err.println("No Class Found");
}
}
|
cs |
- Class객체 해당 Class 정보들을 가져오고, 메서드, 필드에 대한 정보를 출력하는 코드다
- Class.forName() : 해당 클래스 객체에 대한 정보를 가져온다!
- getDeclaredMethods() : 클래스에 정의된 모든 메소드(접근자, 리턴타입, 파라미터)에 대한 정보를 가져온다!
- getDeclaredFields() : 클래스에 포함된 모든 인스턴스 필드의 정보를 가져온다!
Why Reflection?
- 확장성 때문에 사용한다!
- 프로그램의 일부를 자동으로 동기화 할 수 있다!
- 클래스를 동적으로 가져오고, 객체를 프로그래머가 마음대로 사용할 수 있기에 제약이 없어진다.
- 디버깅 및 테스트 도구로 접근이 제한된 인스턴스를 검사할 수 있다!
- 주로 프레임워크 작업단계에서 프레임워크 작성자가 클래스 이름을 모를 때 혹은 클래스 이름이 바뀌었을 때 제일 유용하다!
- 객체를 라이브러리로 이용한다는 점에서 의미가 깊은 방식이다!
* But, 단점도 존재합니다...
- 성능 오버 헤드로 인해 일반적인 접근방식보다는 많이 느리다!
- 리플렉션 코드자체가 너무 복잡하다 = 가독성 저하
- Java 보안 제약 조건 위반을 허용하게 되버린다.
사용법
1
2
3
4
5
|
for (Method method : methods) {
Method methodCall = c.getDeclaredMethod(method.getName());
methodCall.setAccessible(true);
methodCall.invoke(go);
}
|
cs |
- 해당 클래스 내에 모든 메소드 호출을 이렇게나 간략하게 할 수가 있다!!
- 예제 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Go go = new Go();
Class c = go.getClass();
System.out.println(c.getName());
try {
Constructor cons = c.getConstructor();
System.out.println(cons.toString());
Method[] methods = c.getMethods();
for (Method method : methods) { // 메소드 이름 출력 기능
System.out.println(method.getName());
}
// 필드의 정보를 가져온다!
Field field = c.getDeclaredField("s");
field.setAccessible(true);
field.set(go, "hahaha");
System.out.println(go.getS());
// 메소드에 파라미터를 집어넣어서 호출
Method methodCall = c.getDeclaredMethod("method2", int.class);
methodCall.invoke(go, 12);
Method methodCall2 = c.getDeclaredMethod("method3");
methodCall2.setAccessible(true); // 액세스 접근자와 상관없이 메소드 호출가능
methodCall2.invoke(go);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Go {
private String s;
public Go() {
this.s = "This is Go";
}
public String getS() {
return s;
}
public void method1() {
System.out.println("Hi Method 1");
}
public void method2(int a) {
System.out.println(a + "번 숫자 입니다!");
}
private void method3() {
System.out.println("Hi Method 3");
}
}
|
cs |
참고
Java Reflection
Reflection in Java
'Developer > Kotlin & Java' 카테고리의 다른 글
SOLID - LSP(Liskov Substitution Principle)이란? 리스코프 치환 원칙 (0) | 2019.11.22 |
---|---|
SOLID - OCP(Open Closed Principle) : 개방 폐쇄 원칙 (0) | 2019.11.17 |
SOLID - SRP(Single Responsibility Principle) : 단일책임 원칙 (2) | 2019.11.17 |
[자바] 동기화 처리 - Synchronized 와 Asynchronized (2) | 2019.04.10 |
JVM에 대해 파해쳐보자 (0) | 2019.04.05 |