초보 개발자로써 1차전직도 하지못한 지금 멘토링을 진행하는중 멘토님의 권유로 Reflection에 대해서 공부해보고자 한다.(2달만에 블로그 포스팅하는 내 자신에대해 반성하고 시작해야겠다.)
이글을 통하여 구체적인 사용법을 익히는 것이 아닌 개념적인 부분에 대해서 이해해 보고자 한다.
(이유는 다 읽어보면 알 수 있다.)
1. Reflection API 란?
Reflection API 는 구체적인 클래스 타입을 알지 못해도 해당 클래스 정보에 접근할 수 있도록 해주는 java API 이다.
Reflection 을 사용하면 어떤 장점이 있는가?
Reflection API 는 애플리케이션 개발보다는 프레임워크나 라이브러리에서 많이 사용되는 API 이다.
프레임워크나 라이브러리는 사용자가 어떤 클래스를 만들지 예측할 수 없기 때문에 동적으로 해결해주기 위해서 Reflection API 를 사용한다.
실제로 intellij 의 자동완성이나 Spring framework 등등 많은 프레임워크나 라이브러리에서 Reflection 을 사용하고 있다.
Spring Framework 를 사용하면서 기본 생성자를 필요로 하는 어노테이션( ex) Spring Data JPA 의 @Entity )의 경우
애플리케이션이 실행한 후 런타임에 객체가 호출될 때 동적으로 객체의 인스턴스를 생성할때 Reflection 이 사용된다.
Reflection API 로 가져올 수 없는 정보 중 하나가 생성자의 인자 정보이다.
기본 생성자가 반드시 있어야 객체를 생성할 수 있는 것이다.
기본생성자로 객체를 생성만 하면 필드 값 등은 Reflection API 로 넣어주는 것이 가능하다.
다음은 Reflection API 를 사용하여 가져올 수 있는 정보들이다.
- ClassName
- Class Modifilers (public, private, synchronized ...)
- Package Info
- Superclass
- Implements Interfaces
- Constructors
- MethodsFields
- Annotation
2. 간단한 사용법
간단하게 사용법을 알기 위해서 Post 클래스를 생성해보자
public class Post {
private final String title;
private int hit;
public Post(String title, int hit) {
this.title = title;
this.hit = hit;
}
public void clickPost(){
this.hit++;
}
public int getHit() {
return hit;
}
}
main 메소드를 만들고 Post 객체를 다형성을 이용하여 Object 타입으로 받아서 Post 클래스의 메소드를 작성하면
당연하게도 형변환을 하지 않았으므로 컴파일 에러가 발생한다.
Reflection API 를 사용하여 main 메소드를 수정해보자.
public class Main {
public static void main(String[] args) {
Object post = new Post("title",0);
Class postClass = Post.class;
try{
Method click = postClass.getMethod("clickPost");
// clickPost 메서드 실행, invoke(메서드를 실행시킬 객체, 해당 메서드에 넘길 인자)
click.invoke(post, null);
Method getHit = postClass.getMethod("getHit");
int hit = (int)getHit.invoke(post, null);
// 출력 결과: 1
System.out.println(hit);
}catch (Exception e){
}
}
}
이러한 클래스의 정보를 가져올 수 있는 이유는 JVM이 실행되면 자바 코드가 컴파일러를 거쳐 바이트 코드로 변환되어 static 영역에 저장되게 된다.
Reflection API 는 이 정보를 활용해서 클래스 이름만 알고 있다면 static 영역에서 정보를 가져와 사용하게 되는것이다.
3. 결론
Reflection 의 기능은 분명 강력하지만 치명적인 단점 또한 존재한다고 한다.
컴파일 타임이 아니라 런타임에서 동적으로 타입을 분석하고 정보를 가져오므로 JVM 을 최적화할 수 없고, 접근할 수 없는 private 멤버 변수, 메서드 등에 접근하기 때문에 내부를 노출하게 된다.
위에서 작성한 main 메소드에서 Post 객체를 Object 타입으로 받아오는것을 보고 알 수 있듯이 애플리케이션 개발중에는 클래스를 알고 작성하는 경우가 대부분일거고, 사실상 사용할 일이 없는 API 이다.
하지만 앞으로 JAVA 프레임워크나 라이브러리를 사용할때 Reflection 관련 용어가 등장한다면,
'프레임워크에서 동적으로 객체의 인스턴스를 생성하기 위해서 사용하는구나' 라고 이해하면 좋을것 같다.
참고 : https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/
참고 : https://brunch.co.kr/@kd4/8
'JAVA' 카테고리의 다른 글
Java BCI (Byte Code Instrument) (0) | 2022.06.26 |
---|---|
JAVA 의 Garbage Collection (0) | 2022.04.14 |
Volatile 을 사용한 가시성 보장 (0) | 2022.03.15 |
쓰레드의 지역변수 ThreadLocal (0) | 2022.03.15 |
일급 컬렉션 (First Class Collection) 을 사용하자 (0) | 2022.03.01 |
String , StringBuilder, StringBuffer 속도차이 비교 (0) | 2022.02.09 |