카테고리 없음

Java Reflection

뽀글뽀글 개발자 2024. 9. 23. 14:56

 

프레임워크들이 어떻게 동작하는지 궁금할 때 Reflection 개념을 알아두면 이해에 도움이 될 것 같아 정리해보았다.

 

Reflection

구체적인 클래스 타입을 알지 못해도 그 클래스의 정보(메서드, 타입, 변수 등등)에 접근할 수 있게 해주는 자바 API이다.

 

public class Car {
    private final String name;
    private int position;

    public Car(String name, int position) {
        this.name = name;
        this.position = position;
    }

    public void move() {
        this.position++;
    }

    public int getPosition() {
        return position;
    }
}
public static void main(String[] args) {
    Object obj = new Car("foo", 0);
    obj.move();    // 컴파일 에러 발생 java: cannot find symbol
}

위 코드의 obj.move()에서 컴파일 에러가 발생하게 된다.

그 이유는 Java는 컴파일 타임에 타입을 결정하기 때문으로 obj는 Object의 메서드만 사용할 수 있다.

 

public static void main(String[] args) throws Exception {
    Object obj = new Car("foo", 0);
    Class carClass = Car.class;
    Method move = carClass.getMethod("move");

    // move 메서드 실행, invoke(메서드를 실행시킬 객체, 해당 메서드에 넘길 인자)
    move.invoke(obj, null);

    Method getPosition = carClass.getMethod("getPosition");
    int position = (int)getPosition.invoke(obj, null);
    System.out.println(position);
    // 출력 결과: 1
}

Reflection을 사용하면 위와 같이 Object 타입으로 선언된 객체도 Car의 메서드를 사용할 수 있게된다.

Reflection API는 컴파일되어 JVM의 static 영역에 있는 자바 코드를 참조하기 때문에 클래스의 타입을 몰라도 클래스의 이름만 알면 사용할 수 있는 것이다.

 

 

어디에 사용하는가?

Reflection은 프레임워크나 라이브러리 같이 사용자가 어떤 클래스를 만들지 예측할 수 없는 경우 동적으로 클래스를 바인딩하기 위해 사용한다.

IDE에서 자동으로 Getter, Setter를 만들 수 있고, Junit 처럼 @Test를 찾아갈 수 있으며, JPA의 엔티티를 테이블에 매핑하는 작업 역시 Reflection이 필요하다.

 

 

개발 시 클래스를 모를 일이 잘 없고 아래와 같은 단점으로 인해 직접 사용할 일은 잘 없다.

  • 성능 오버헤드가 있다.
    • 컴파일 타임이 아닌 런타임에 동적으로 타입을 분석하고 정보를 가져오기 때문에 JVM을 최적화할 수 없다.
  • 캡슐화 위반
    • 직접 접근할 수 없는 private 인스턴스 변수나 메서드에 접근할 수 있어, 객체의 내부를 노출시키고 추상화를 깨뜨릴 수 있다.

 

 

Reference

https://tecoble.techcourse.co.kr/post/2020-07-16-reflection-api/