Java

μžλ°” λ¦¬ν”Œλ ‰μ…˜

devJK93 2024. 12. 7.

πŸ“ Java Reflection

Java Reflection은 λŸ°νƒ€μž„(Run-time)에 클래슀, λ©”μ„œλ“œ, ν•„λ“œ λ“±μ˜ 정보λ₯Ό λ™μ μœΌλ‘œ νƒμƒ‰ν•˜κ³  μ‘°μž‘ν•  수 μžˆλŠ” κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” Java APIμž…λ‹ˆλ‹€. 즉, μ½”λ“œ μ‹€ν–‰ 쀑에 클래슀의 ꡬ쑰λ₯Ό κ²€μ‚¬ν•˜κ±°λ‚˜ μ‘°μž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ¦¬ν”Œλ ‰μ…˜μ€ java.lang.reflect νŒ¨ν‚€μ§€μ™€ java.lang.Class 클래슀λ₯Ό 톡해 μ œκ³΅λ©λ‹ˆλ‹€.

1. λ¦¬ν”Œλ ‰μ…˜μ˜ μ£Όμš” κΈ°λŠ₯

  • 클래슀 정보 쑰회: 클래슀 이름, νŒ¨ν‚€μ§€ 이름, λΆ€λͺ¨ 클래슀, κ΅¬ν˜„ μΈν„°νŽ˜μ΄μŠ€ λ“±μ˜ 정보λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν•„λ“œ(Field) 쑰회 및 μˆ˜μ •: 클래슀의 멀버 λ³€μˆ˜λ₯Ό λ™μ μœΌλ‘œ 읽고 μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • λ©”μ„œλ“œ(Method) 호좜: 클래슀의 λ©”μ„œλ“œλ₯Ό λ™μ μœΌλ‘œ ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μƒμ„±μž(Constructor) 호좜: 클래슀λ₯Ό λ™μ μœΌλ‘œ μΈμŠ€ν„΄μŠ€ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μ–΄λ…Έν…Œμ΄μ…˜(Annotation) 쑰회: 클래슀, λ©”μ„œλ“œ, ν•„λ“œμ— μ •μ˜λœ μ–΄λ…Έν…Œμ΄μ…˜ 정보λ₯Ό λ™μ μœΌλ‘œ 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

2. λ¦¬ν”Œλ ‰μ…˜μ˜ κΈ°λ³Έ API

λ¦¬ν”Œλ ‰μ…˜μ€ λ‹€μŒκ³Ό 같은 μ£Όμš” ν΄λž˜μŠ€μ™€ λ©”μ„œλ“œλ₯Ό 톡해 μ‚¬μš©λ©λ‹ˆλ‹€:

1) Class 클래슀

λͺ¨λ“  Java 객체의 메타데이터λ₯Ό μ œκ³΅ν•˜λŠ” ν΄λž˜μŠ€μž…λ‹ˆλ‹€. Class κ°μ²΄λŠ” λ¦¬ν”Œλ ‰μ…˜μ˜ μ‹œμž‘μ μž…λ‹ˆλ‹€.

Class 객체 κ°€μ Έμ˜€λŠ” 방법:


// 1. 클래슀 μ΄λ¦„μœΌλ‘œ κ°€μ Έμ˜€κΈ°
Class<?> clazz = MyClass.class;

// 2. κ°μ²΄λ‘œλΆ€ν„° κ°€μ Έμ˜€κΈ°
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();

// 3. 클래슀 이름 λ¬Έμžμ—΄λ‘œ κ°€μ Έμ˜€κΈ°
Class<?> clazz = Class.forName("com.example.MyClass");
        

2) ν•„λ“œ(Field) μ ‘κ·Ό

예제: 클래슀 ν•„λ“œ 쑰회 및 κ°’ μ„€μ •


import java.lang.reflect.Field;

class Person {
    private String name = "John";
    public int age = 30;
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Person person = new Person();

        // Class 객체 κ°€μ Έμ˜€κΈ°
        Class<?> clazz = person.getClass();

        // ν•„λ“œ 정보 κ°€μ Έμ˜€κΈ°
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true); // private ν•„λ“œμ— μ ‘κ·Ό ν—ˆμš©

        // ν•„λ“œ κ°’ 읽기
        String nameValue = (String) nameField.get(person);
        System.out.println("Name: " + nameValue); // 좜λ ₯: Name: John

        // ν•„λ“œ κ°’ μ„€μ •
        nameField.set(person, "Alice");
        System.out.println("Updated Name: " + nameField.get(person)); // 좜λ ₯: Updated Name: Alice
    }
}
        

3) λ©”μ„œλ“œ(Method) 호좜

예제: λ©”μ„œλ“œ ν˜ΈμΆœν•˜κΈ°


import java.lang.reflect.Method;

class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Calculator calculator = new Calculator();

        // Class 객체 κ°€μ Έμ˜€κΈ°
        Class<?> clazz = calculator.getClass();

        // λ©”μ„œλ“œ κ°€μ Έμ˜€κΈ°
        Method addMethod = clazz.getDeclaredMethod("add", int.class, int.class);

        // λ©”μ„œλ“œ 호좜
        int result = (int) addMethod.invoke(calculator, 10, 20);
        System.out.println("Result: " + result); // 좜λ ₯: Result: 30
    }
}
        

4) μƒμ„±μž(Constructor) 호좜

예제: 객체 동적 생성


import java.lang.reflect.Constructor;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "'}";
    }
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // Class 객체 κ°€μ Έμ˜€κΈ°
        Class<?> clazz = Person.class;

        // μƒμ„±μž κ°€μ Έμ˜€κΈ°
        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);

        // 동적 객체 생성
        Person person = (Person) constructor.newInstance("John");
        System.out.println(person); // 좜λ ₯: Person{name='John'}
    }
}
        

5) μ–΄λ…Έν…Œμ΄μ…˜(Annotation) 정보 쑰회

예제: 클래슀의 μ–΄λ…Έν…Œμ΄μ…˜ 확인


import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String value();
}

@MyAnnotation("Test Class")
class TestClass {}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // Class 객체 κ°€μ Έμ˜€κΈ°
        Class<?> clazz = TestClass.class;

        // μ–΄λ…Έν…Œμ΄μ…˜ 확인
        if (clazz.isAnnotationPresent(MyAnnotation.class)) {
            MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
            System.out.println("Annotation Value: " + annotation.value()); // 좜λ ₯: Annotation Value: Test Class
        }
    }
}
        

3. λ¦¬ν”Œλ ‰μ…˜μ˜ μž₯점

  • 동적 λ™μž‘ κ΅¬ν˜„: λŸ°νƒ€μž„μ— 클래슀의 ꡬ쑰λ₯Ό λ™μ μœΌλ‘œ ν™•μΈν•˜κ³ , 객체λ₯Ό μ‘°μž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • μœ μ—°μ„±: 컴파일 μ‹œμ μ— μ•Œ 수 μ—†λŠ” ν΄λž˜μŠ€λ‚˜ λ©”μ„œλ“œμ— λ™μ μœΌλ‘œ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. ν”ŒλŸ¬κ·ΈμΈ μ‹œμŠ€ν…œ, μ˜μ‘΄μ„± μ£Όμž…, JSON 직렬화 등에 ν™œμš©λ©λ‹ˆλ‹€.

4. λ¦¬ν”Œλ ‰μ…˜μ˜ 단점

  • μ„±λŠ₯ 문제: λ¦¬ν”Œλ ‰μ…˜μ€ 일반 λ©”μ„œλ“œ ν˜ΈμΆœλ³΄λ‹€ λŠλ¦½λ‹ˆλ‹€. λ‚΄λΆ€μ μœΌλ‘œ λ§Žμ€ 검증 μž‘μ—…μ΄ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.
  • μ•ˆμ „μ„± 문제: 컴파일 νƒ€μž„μ— κ²€μ¦λ˜μ§€ μ•ŠμœΌλ―€λ‘œ λŸ°νƒ€μž„ μ—λŸ¬κ°€ λ°œμƒν•  κ°€λŠ₯성이 λ†’μŠ΅λ‹ˆλ‹€.
  • λ³΄μ•ˆ 문제: λ¦¬ν”Œλ ‰μ…˜μœΌλ‘œ private ν•„λ“œλ‚˜ λ©”μ„œλ“œμ— μ ‘κ·Όν•  수 μžˆμœΌλ―€λ‘œ λ³΄μ•ˆμƒμ˜ λ¦¬μŠ€ν¬κ°€ μžˆμŠ΅λ‹ˆλ‹€.

5. λ¦¬ν”Œλ ‰μ…˜μ˜ ν™œμš© 사둀

  • ν”„λ ˆμž„μ›Œν¬ 개발: Spring, Hibernate λ“±μ—μ„œ μ˜μ‘΄μ„± μ£Όμž…(Dependency Injection), 동적 ν”„λ‘μ‹œ 생성 등에 μ‚¬μš©λ©λ‹ˆλ‹€.
  • JSON 직렬화/역직렬화: 객체λ₯Ό JSON으둜 λ³€ν™˜ν•˜κ±°λ‚˜ μ—­μ§λ ¬ν™”ν•˜λŠ” λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ ν™œμš©λ©λ‹ˆλ‹€.
  • JUnit ν…ŒμŠ€νŠΈ ν”„λ ˆμž„μ›Œν¬: ν…ŒμŠ€νŠΈ λ©”μ„œλ“œ 동적 싀행에 λ¦¬ν”Œλ ‰μ…˜μ΄ μ‚¬μš©λ©λ‹ˆλ‹€.

'Java' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

μžλ°” enum  (0) 2024.12.09
[Java] JDK, JRE, JVM μ§ˆμ˜μ‘λ‹΅ (ChatGPT)  (1) 2024.08.31
[Java] Reflection  (2) 2024.02.21
Generics (Java)  (1) 2024.02.12
JVM λ©”λͺ¨λ¦¬ ꡬ쑰 (JAVA)  (1) 2024.02.08

λŒ“κΈ€