Java Study

Reflection API in Java

초코너무조코 2025. 1. 22. 20:26
728x90

 

목차

     


    1. Reflection API란?

    • Reflection API: java.lang.reflect 패키지에서 제공되며 클래스, 메서드, 필드, 생성자를 조작할 수 있는 도구.
    • 주요 기능
      • 클래스 이름과 구조를 런타임에 확인 가능.
      • private 필드, 메서드 등 접근 제약을 우회 가능.
      • 동적으로 메서드를 호출하거나 필드 값을 설정 가능.

    2. 주요 클래스와 인터페이스

    2.1 Class<T> 클래스

    • 클래스의 메타데이터를 담고 있는 핵심 객체.
      • Class.forName("패키지.클래스")로 특정 클래스 정보를 로드할 수 있음.
    Class<?> clazz = Class.forName("com.example.MyClass");
    
    • 주요 메서드:
      • getName(): 클래스의 전체 이름(패키지 포함)을 반환.
      • getSimpleName(): 클래스 이름만 반환.
      • getDeclaredFields(): 모든 필드 정보를 배열로 반환.
      • getDeclaredMethods(): 클래스의 모든 메서드 정보 반환.

    2.2 Field 클래스

    • 클래스의 필드(멤버 변수)를 다루는 클래스.
      • 필드 값을 읽고 쓰거나, private 필드에도 접근 가능.
    Field field = clazz.getDeclaredField("fieldName");
    field.setAccessible(true); // private 필드 접근 허용
    field.set(instance, "새 값"); // 필드 값 설정
    Object value = field.get(instance); // 필드 값 가져오기
    

    2.3 Method 클래스

    • 메서드 호출을 다루는 클래스.
      • private 메서드도 호출 가능하며, 메서드의 시그니처에 맞는 인자를 전달해야 함.
    Method method = clazz.getDeclaredMethod("methodName", String.class);
    method.setAccessible(true); // private 메서드 접근 허용
    Object result = method.invoke(instance, "파라미터 값"); // 메서드 호출
    

    2.4 Constructor 클래스

    • 생성자 호출을 다루는 클래스.
      • 파라미터가 있는 생성자나 private 생성자에도 접근 가능.
    Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);
    constructor.setAccessible(true);
    Object instance = constructor.newInstance("초기값");
    

    3. Reflection 사용 예제

    3.1 클래스 정보 가져오기

    • 클래스 이름과 부모 클래스 확인.
      • 클래스의 메타데이터를 활용하여 동적으로 로드.
    Class<?> clazz = String.class;
    System.out.println("클래스 이름: " + clazz.getName());
    System.out.println("상위 클래스: " + clazz.getSuperclass().getName());
    

    3.2 필드 조작

    • private 필드 값을 읽고 수정.
      • setAccessible(true)를 사용하여 접근 제한 우회.
    Class<?> clazz = Class.forName("com.example.MyClass");
    Object instance = clazz.getDeclaredConstructor().newInstance();
    
    Field field = clazz.getDeclaredField("privateField");
    field.setAccessible(true);
    field.set(instance, "새 값"); // 필드 값 설정
    System.out.println("필드 값: " + field.get(instance));
    

    3.3 메서드 호출

    • private 메서드 호출 및 결과 반환.
      • 메서드 이름과 파라미터 타입으로 메서드 찾기.
    Class<?> clazz = Class.forName("com.example.MyClass");
    Object instance = clazz.getDeclaredConstructor().newInstance();
    
    Method method = clazz.getDeclaredMethod("privateMethod", String.class);
    method.setAccessible(true); // private 접근 허용
    Object result = method.invoke(instance, "파라미터 값");
    System.out.println("메서드 호출 결과: " + result);
    

    4. 주의사항 및 한계

    • 성능 저하: Reflection은 일반 메서드 호출보다 느려 런타임 성능에 영향을 줄 수 있음.
    • 캡슐화 위반: private 필드나 메서드에 접근 가능하므로 보안에 민감한 코드에서 주의 필요.
    • 런타임 에러: 컴파일 타임 검증 불가로 실행 중에 예외 발생 가능.

    5. 사용 사례

    • 프레임워크 개발: Spring, Hibernate 등에서 객체 생성과 DI(의존성 주입)에 활용.
    • 테스트 도구: JUnit에서 private 메서드나 필드 테스트에 활용.
    • 동적 로딩: 런타임에 클래스 이름만으로 기능 구현.

     

     

    728x90