본문 바로가기

Java

Java Reflection 알아보기

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

 

'Java' 카테고리의 다른 글

헷갈리는 용어  (0) 2024.05.28
java Overflow(오버플로우)  (0) 2024.05.25
JVM 메모리 구조  (0) 2024.05.14
MAVEN 도서 읽으면서 정리한 내용  (0) 2024.04.01
정렬할때 쓰기 좋은 메소드  (0) 2024.02.15