Java

Java Reflection 알아보기

amungstudy 2024. 5. 16. 12:25

Java Reflection은 이름별로 클래스 및 데이터 구조에 대한 정보의 동적 검색을 지원하고,

실행중인 Java 프로그램 내에서 해당 정보를 조작할 수 있습니다.

 

Java Reflection 활용 예시 : 

Framework, IDE에서 내부적으로 동적 바인딩 기능 사용(프로그램 실행 중 동적으로 클래스 정보 가져옴)

ex. IntelliJ 자동완성, Spring Framework Annotation,
@Getter,@Setter 도 리플렉션을 사용하여 필드 정보를 가져와 구현한다.


ClassLoader 

자바 클래스 로더는 런타임 시 클래스를 동적으로 JVM에 로드하는 역할을 수행한다.

이때, Class 정보를 CLASSPATH(클래스 파일을 찾는데 기준이 되는 파일 경로)에서 찾는다.

 

만약

  1. a() 메서드를 가지고 있는 클래스가 존재한다
  2. 지금은 클래스의이름을 모른다. 나중에 이 클래스의 이름을 알 수 있다
  3. a() 메서드를 실행할 수 있도록 코드를 작성해야한다

고 가정할 때, ClassLoader를 활용할 수 있다.


Class 타입을 통해 클래스의 메서드와 필드 정보에 접근할 수 있다

ClassLoader를 이용하면 인스턴스를 만들 수 있고(JVM이 생성), 메서드도 실행할 수 있다.

 

즉, 문자열로 된 클래스 이름과 문자열로 된 메서드 이름만 있으면 메서드를 실행할 수 있는 것이다.

리플렉션은 접근제어자와 무관하게 클래스의 필드나 메소드를 가져와서 호출할 수 있다.

 

Java Reflection의 단점

1. 일반적인 메소드 호출 시 컴파일 시점에 분석된 클래스를 사용. Reflection은 런타임 시 클래스를 분석하여 속도가 상대적으로 느리다.

2. 컴파일 시점에 타입 체크가 불가능하다

3. 객체의 추상화가 깨진다

 

보통 웹 애플리케이션 개발보다는 라이브러리나 프레임워크 개발 시 사용된다고 한다.

예시 )

public class Bus {

    public void a(){
        System.out.println("a");
    }
    public void b(){
        System.out.println("b");
    }
    public void c(){
        System.out.println("c");
    }
}

 

package javaReflectionExample;

import java.lang.reflect.Method;

public class ClassLoaderMain {
    public static void main(String[] args) throws ClassNotFoundException {
        // 일반적인 메서드 호출 방법
        // Bus bus1 = new Bus();
        // bus1.a();
        
        // 이 이름에 해당하는 클래스 정보를 CLASSPATH에서 읽어들인다
        // 그 정보를 변수가 참조하도록 한다
        String className = "javaReflectionExample.Bus";
        Class clazz = Class.forName(className);
        // 클래스의 메서드 정보를 리턴한다
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods) {
            // 메서드 이름을 출력한다 ( 여기서는 a,b,c가 출력된다)
            System.out.println(m.getName());
        }


    }
}

 

new 연산자 대신 아래와 같은 방식으로 사용 가능.

하지만 아래와 같은 코드는 형변환 필요.

 

package javaReflectionExample;

import java.lang.reflect.Method;

public class ClassLoaderMain {
    public static void main(String[] args) throws Exception {
        // 일반적인 메서드 호출 방법
        // Bus bus1 = new Bus();
        // bus1.a();

        // 이 이름에 해당하는 클래스 정보를 CLASSPATH에서 읽어들인다
        // 그 정보를 변수가 참조하도록 한다
        String className = "javaReflectionExample.Bus";
        Class clazz = Class.forName(className);
        Object o = clazz.newInstance(); //JDK9 부터 deprecated
        Bus b = (Bus)o; // 형변환 가능
        b.a(); // 정상 실행 가능(실행결과 : a)


    }
}

 

추상 클래스와 상속을 이용해서 형변환 처리할 수 있음

그런데, 상속 하지 않은 클래스는 어떻게 처리하지?

-> Java의 Reflect 문법을 이용한다.

 

String className = "javaReflectionExample.MyHome";
Class clazz = Class.forName(className);
Object o = clazz.newInstance(); //JDK9 부터 deprecated


// a() 메소드 정보를 가지고 있는 Method 반환
Method m = clazz.getDeclaredMethod("a", null);
// Object o 가 참조하는 객체의 m 메소드를 실행하라
m.invoke(o,null); // 실행 결과 MyHome 객체의 a()가 실행됨

 

 

 

참조 :

https://www.oracle.com/technical-resources/articles/java/javareflection.html

 

Using Java Reflection

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all

www.oracle.com

 

https://www.inflearn.com/course/%EC%A6%90%EA%B1%B0%EC%9A%B4-%EC%9E%90%EB%B0%94#reviews

 

[지금 무료] 즐거운 자바 | 부부 개발단 토토(김성박) - 인프런

부부 개발단 토토(김성박) | 기업에서 가장 많이 사용하는 프로그래밍 언어중 대표적인 언어를 말하라고 하면 Java언어를 말할 것 같아요. 즐거운 자바 교육과 함께 즐겁게 자바 공부를 진행해보

www.inflearn.com

https://hudi.blog/java-reflection/#%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0

 

자바 리플렉션 (Reflection) 기초

리플렉션 (Reflection) JVM은 클래스 정보를 클래스 로더를 통해 읽어와서 해당 정보를 JVM 메모리에 저장한다. 그렇게 저장된 클래스에 대한 정보가 마치 거울에 투영된 모습과 닮아있어, 리플렉션

hudi.blog