[TIL] 45. 리플렉션(Reflection)

김지수·2024년 6월 24일

TIL

목록 보기
46/53

Reflection

프로그램이 자신의 구조를 분석하고 수정할 수 있는 능력을 말합니다. Java에서는 리플렉션을 통해 실행 중인 클래스의 메서드, 필드, 생성자 등에 접근할 수 있습니다. 이를 통해 컴파일 시간에 알 수 없는 클래스나 인터페이스의 구조에 접근하고 조작할 수 있습니다.

주요 개념 및 기능

Class 객체 가져오기

모든 객체는 클래스를 가지고 있고, Java의 Class 클래스는 클래스와 인터페이스에 대한 메타데이터를 제공합니다.
예를 들어, String.class는 String 클래스의 Class 객체를 반환합니다.
Field, Method, Constructor 접근:

Class.getDeclaredField(String name)

주어진 이름의 필드를 반환합니다.
Class.getDeclaredFields(): 클래스에 정의된 모든 필드의 배열을 반환합니다.
Class.getDeclaredMethod(String name, Class<?>... parameterTypes): 주어진 이름과 매개변수 유형의 메서드를 반환합니다.
Class.getDeclaredConstructor(Class<?>... parameterTypes): 주어진 매개변수 유형의 생성자를 반환합니다.

접근성 설정

Field.setAccessible(true): private 접근 제어자가 붙은 필드에 접근할 수 있도록 합니다.

동적 객체 생성 및 메서드 호출

Constructor.newInstance(Object... initargs)동적으로 객체를 생성합니다.
Method.invoke(Object obj, Object... args): 객체의 메서드를 호출합니다.

애너테이션 처리

Field.getAnnotations(), Method.getAnnotations(): 필드나 메서드에 적용된 애너테이션을 가져올 수 있습니다.

import java.lang.reflect.*;

public class ReflectionExample {

    public static void main(String[] args) throws Exception {
        // 클래스 이름을 통해 Class 객체 가져오기
        Class<?> cls = Class.forName("java.lang.String");

        // 클래스의 생성자 정보 가져오기
        Constructor<?>[] constructors = cls.getDeclaredConstructors();
        System.out.println("Constructors:");
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        // 클래스의 필드 정보 가져오기
        Field[] fields = cls.getDeclaredFields();
        System.out.println("\nFields:");
        for (Field field : fields) {
            System.out.println(field);
        }

        // 클래스의 메서드 정보 가져오기
        Method[] methods = cls.getDeclaredMethods();
        System.out.println("\nMethods:");
        for (Method method : methods) {
            System.out.println(method);
        }

        // 동적으로 객체 생성하기
        Constructor<?> constructor = cls.getDeclaredConstructor(String.class);
        constructor.setAccessible(true); // private 생성자 접근 가능하게 설정
        Object obj = constructor.newInstance("Hello Reflection!");

        // 동적으로 메서드 호출하기
        Method method = cls.getDeclaredMethod("toUpperCase");
        Object result = method.invoke(obj);
        System.out.println("\nResult of toUpperCase(): " + result);
    }
}

주의사항

성능 저하

리플렉션은 정적 코드보다 느릴 수 있으며, 컴파일 타임에 오류를 검출할 수 없는 가능성이 있습니다.

보안 문제

setAccessible(true)를 사용하면 보안 검사를 우회할 수 있으므로 주의해야 합니다.
리플렉션은 일반적으로 런타임에 동적으로 클래스의 구조를 탐색하거나 수정해야 할 때 유용합니다. 하지만 사용 시에는 신중하게 접근하고, 필요한 경우에만 사용하는 것이 좋습니다.

오늘의 회고


테스트 코드 짜면서 set 이랑 Builder를 사용 안하고 해보고 싶어서 찾아 봤더니 리플렉션이라는 걸 알게 되어 이번 과제에 테스트 코드에 적용해 보았다.

profile
서툴고 부족한 점이 많지만, 배우고 발전하며 성장하기 위해 노력하겠습니다.

0개의 댓글