Files
java-examples/docs/Reflection.md

6.9 KiB

자바 리플렉션(Reflection) 쉽게 배우기

1. 리플렉션이란?

리플렉션(Reflection)이란 실행 중에 클래스의 정보를 조회하고, 필드·메서드·생성자를 동적으로 조작하는 기능이다.
즉, 컴파일 시점이 아니라 런타임(실행 중)에 클래스 내부를 들여다보고 조작할 수 있다.


2. 주요 클래스 및 메서드 정리

(1) Class 클래스 (클래스 정보 조회)

메서드 설명
Class.forName("클래스명") 클래스 객체 가져오기 (정적 로드)
Object.getClass() 인스턴스로부터 클래스 객체 얻기
getName() 클래스 전체 이름 (패키지.클래스명) 반환
getSimpleName() 클래스 단순 이름 반환
getDeclaredFields() 선언된 모든 필드(Field[]) 조회
getDeclaredMethods() 선언된 모든 메서드(Method[]) 조회
getDeclaredConstructors() 선언된 모든 생성자(Constructor[]) 조회

예제 코드 (클래스 정보 출력)

Class<?> clazz = Class.forName("java.util.ArrayList");

System.out.println("클래스 이름: " + clazz.getName());
System.out.println("간단한 이름: " + clazz.getSimpleName());
System.out.println("패키지: " + clazz.getPackage().getName());

클래스의 이름과 패키지 정보를 확인할 수 있다!


(2) Field 클래스 (필드 정보 조회 및 수정)

메서드 설명
getName() 필드 이름 가져오기
getType() 필드 타입 가져오기
getModifiers() 접근 제어자 가져오기
setAccessible(true) private 필드 접근 가능하게 설정
get(Object obj) 특정 객체의 필드 값 가져오기
set(Object obj, Object value) 특정 객체의 필드 값 변경

예제 코드 (필드 조회 및 값 변경)

import java.lang.reflect.*;

class Person {
    private String name = "John";
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        Class<?> clazz = person.getClass();
        
        Field field = clazz.getDeclaredField("name");
        field.setAccessible(true); // private 접근 허용
        
        System.out.println("기존 값: " + field.get(person));
        field.set(person, "Alice"); // 값 변경
        System.out.println("변경된 값: " + field.get(person));
    }
}

private 필드도 강제로 조작할 수 있다!


(3) Method 클래스 (메서드 정보 조회 및 호출)

메서드 설명
getName() 메서드 이름 가져오기
getParameterTypes() 메서드 매개변수 타입 가져오기
getReturnType() 반환 타입 가져오기
invoke(Object obj, Object... args) 메서드 실행

예제 코드 (메서드 실행)

import java.lang.reflect.*;

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

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Calculator calc = new Calculator();
        Class<?> clazz = calc.getClass();
        
        Method method = clazz.getDeclaredMethod("add", int.class, int.class);
        method.setAccessible(true); // private 접근 허용
        
        int result = (int) method.invoke(calc, 5, 10); // 메서드 실행
        System.out.println("결과: " + result);
    }
}

private 메서드도 실행할 수 있다!


(4) Constructor 클래스 (생성자 정보 조회 및 인스턴스 생성)

메서드 설명
getParameterTypes() 생성자 매개변수 타입 가져오기
newInstance(Object... initargs) 새로운 인스턴스 생성

예제 코드 (객체 동적 생성)

import java.lang.reflect.*;

class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Person.class;
        
        Constructor<?> constructor = clazz.getConstructor(String.class);
        Object person = constructor.newInstance("Charlie"); // 동적 생성
        
        Method method = clazz.getMethod("getName");
        System.out.println("이름: " + method.invoke(person)); // Charlie 출력
    }
}

리플렉션을 이용해 생성자를 실행하고 객체를 만들 수 있다!


(5) Modifier 클래스 (접근 제어자 확인)

메서드 설명
isPublic(int mod) public 여부 확인
isPrivate(int mod) private 여부 확인
isStatic(int mod) static 여부 확인

예제 코드 (필드 접근 제어자 확인)

import java.lang.reflect.*;

class Sample {
    private int num;
    public static String text;
}

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        Field field = Sample.class.getDeclaredField("text");
        int modifiers = field.getModifiers();
        
        System.out.println("static인가? " + Modifier.isStatic(modifiers)); // true
        System.out.println("public인가? " + Modifier.isPublic(modifiers)); // true
    }
}

필드나 메서드가 public, private, static인지 확인할 수 있다!


3. 리플렉션의 활용 예시

DI(의존성 주입) 프레임워크(Spring) → 리플렉션으로 객체를 생성하고 자동 주입
JUnit 테스트 프레임워크@Test 붙은 메서드 자동 실행
JSON 라이브러리(Jackson, Gson) → 객체를 JSON으로 변환할 때 필드 조회
프록시 패턴(AOP, 동적 프록시) → 런타임에 동적 메서드 실행


4. 리플렉션의 단점과 주의점

성능 저하 → 리플렉션은 일반 메서드 호출보다 느리다. 자주 사용하면 성능 문제가 생길 수 있다.
보안 문제setAccessible(true)로 private 필드/메서드에 접근할 수 있어 보안 위험이 있다.
컴파일 타임 체크 불가능 → 오타나 잘못된 메서드 호출은 실행 시점에서야 오류가 발생한다.

따라서, 꼭 필요한 경우에만 사용하고 남용하지 않는 것이 좋다!


5. 정리

리플렉션은 실행 중 클래스 정보를 조회하고 조작할 수 있는 기능이다!
Class, Field, Method, Constructor 클래스를 활용하면 필드 값 변경, 메서드 실행, 객체 생성 등이 가능하다!
Spring, JSON 파싱, 테스트 프레임워크 등에서 널리 사용된다!
하지만 성능 저하와 보안 문제를 고려하여 신중히 사용해야 한다!

리플렉션을 잘 활용하면, 자바 프로그램을 더 유연하게 만들 수 있다!