코딩마을방범대
Java의 Reflection 기능을 사용하는 방법 본문
728x90
Reflection
- 클래스의 구조를 분석하여 동적 로딩을 가능하게 하는 기능
- 힙 영역에 로드된 Class 타입의 객체를 통해 원하는 클래스의 인스턴스를 생성할 수 있도록 지원하고,
인스턴스의 필드와 메소드를 접근 제어자와 상관 없이 사용할 수 있도록 지원하는 API
장점
- 런타임 시점에서 클래스의 인스턴스를 생성하고, 접근 제어자와 관계 없이 필드와 메소드에 접근하여 필요한 작업을 수행할 수 있는 유연성을 가지고 있다.
단점
- 캡슐화를 저해한다.
- 런타임 시점에서 인스턴스를 생성하므로 컴파일 시점에서 해당 타입을 체크할 수 없고,
구체적인 동작 흐름을 파악하기 어렵다. - 단순히 필드 및 메소드를 접근할 때보다 리플렉션을 사용하여 접근할 때 성능이 느리다.
(모든 상황에서 성능이 느리지는 않음.)
사용하기
Reflection 기능을 활용하여 가져올 수 있는 항목은 크게 네 가지가 있다.
- new 를 사용하지 않고 인스턴스를 생성할 수 있다.
- 인스턴스의 메소드를 가져올 수 있다.
- 인스턴스의 변수를 가져올 수 있다.
- 어노테이션을 가져올 수 있다.
Class
Reflection의 기능을 통해서 인스턴스를 생성할 수 있다.
// User 클래스의 타입을 선언한다.
Class<?> cls = User.class;
// Node 클래스의 생성자를 취득한다.
Constructor<?> constructor = cls.getConstructor();
// 생성자를 통해 newInstance 함수를 호출하여 Node 인스턴스를 생성한다.
User user = (User) constructor.newInstance();
💡 클래스 타입을 가져오는 세 가지 방법!
- 클래스명.class
- Class.forName("경로.클래스명");
- 객체.getClass()
Class.forName() 을 통해 클래스 타입을 가져올 경우 장점!
컴파일할 때, 해당 클래스를 만들지 않아도 생성이 가능합니다.
즉, 실행할 때만 해당 클래스가 있으면 되어 동적 바인딩이 가능하다.
Method
Class의 Method를 가져와 실행시킬 수 있다.
// User라는 클래스의 subscribe 메소드를 가져온다.
Method method = Class.forName("User").getMethod("subscribe");
// 저장한 subscribe 메소드의 인수에 User 클래스를 넣어 실행한다.
method.invoke(Class.forName("User"));
💡 실행할 메소드에 파라미터가 존재하는 경우?
만약 파라미터가 있는 메소드를 실행해야할 경우에는 getMethod 시 인자의 타입을 순서대로 명시해주면 된다.
User 클래스의 print 라는 메소드의 파라미터가 (String, int) 일 경우 아래와 같이 실행하면 된다.
// 클래스에서 String, int 파라미터를 가진 print함수를 취득한다.
method = cls.getMethod("print", String.class, Integer.TYPE);
// 취득한 함수에 생성한 인스턴스와 파라미터 값을 넣고 실행시킨다.
method.invoke(user, "test2", 100);
private이나 protected 가 붙은 메소드를 활용해야할 경우?
method.setAccessible(true);
getMethods와 getDeclaredMethods의 차이점
※ @Data 어노테이션 같은 경우 Get, Set 메소드가 각각 출력됨!
메소드 | 설명 |
getMethods() | 오브젝트부터 해당 클래스까지의 메소드 전부를 가져옴 ( equals, toString, hashCode 등이 포함되어 있음 ) |
getDeclaredMethods() | 해당 클래스의 메소드들을 가져옴 |
Variable
Class의 변수들을 가져와 사용할 수 있다.
// Reflection으로 data 변수를 취득한다.
Field field = User.class.getDeclaredField("name");
// setAccessible는 private, protected도 접근 가능하게 한다.
field.setAccessible(true);
// 인스턴스와 인수값을 주어 세팅할 수 있다.
field.set(user, 100);
getFields와 getDeclaredFields의 차이점
※ 실질적으로 변수를 public으로 선언하는 경우는 없기 때문에 Declared를 많이 사용함
메소드 | 설명 |
getFields() | public 필드만 가져옴 |
getDeclaredFields() | public과 private 필드 전부 가져옴 |
Annotation
클래스나 메소드 등에 부여된 어노테이션을 가져온다.
// User에서 AccessRole 이라는 클래스명을 가진 어노테이션을 가져옴
Annotation ann = User.class.getAnnotation(AccessRole.class);
// 어노테이션에 인수값으로 들어간 값을 가져옴
ann.role();
참고사이트
Reflection 기능을 사용하는 방법 - Class편
728x90
'💡 백엔드 > Java' 카테고리의 다른 글
자바에서 유니크한 값 가져오기 ( UUID / random ) (0) | 2023.07.27 |
---|---|
Java에서 QR 코드 만들기 (0) | 2023.07.27 |
Java에서 OS의 시스템에 접근하기 (0) | 2023.07.25 |
SpringBoot에서 Slack Webhoook 사용하기 (0) | 2023.07.25 |
Optional에 대하여 (0) | 2023.07.25 |