Reflection에 대해 쓰기 전에 먼저 Class 객체에 대해서 먼저 정리해보자.
Class 객체
정의
- Class는 모든 자바 클래스의 '메타데이터(설계도)'를 담는 그릇
- 일반 객체(new Person())는 실제 사람 인스턴스
- Class<Person>은 사람이라는 설계도 자체
왜 Class<?>를 쓰는가?
어떤 클래스가 올지 모를때 사용한다.
(추가로, 어떤 객체가 올지 모를때 사용된다는 점은 비슷하지만 Object는 실제 객체를 담는 것이고, Class는 클래스의 메타데이터를 담는다.)
Object obj = new Person(); // 실제 Person 객체가 들어감
Class<?> clazz = Person.class; // Person의 설계도
Object obj = clazz.getDeclaredConstructor().newInstance(); // 설계도로 객체 생성
실제 프로젝트에서 봤던 코드
Class<?> clazz = vo.getClass();
Field[] fields = clazz.getDeclaredFields();
여기서 나오는 '.getDeclaredFields()'는 Class<?> 객체가 가진 모든 필드(멤버 변수)를 Field 객체 배열로 반환하는 메서드다.
예를 들어,
class Person {
private String name;
public int age;
}
public class FieldDetailExample {
public static void main(String[] args) throws Exception {
Class<?> clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("toString(): " + field); // Field 객체의 문자열 표현
System.out.println("이름: " + field.getName());
System.out.println("타입: " + field.getType());
System.out.println("접근제어자: " + java.lang.reflect.Modifier.toString(field.getModifiers()));
System.out.println("------");
}
}
}
위와 같이 코딩하면,
| toString(): private java.lang.String Person.name 이름: name 타입: class java.lang.String 접근제어자: private ------ toString(): public int Person.age 이름: age 타입: int 접근제어자: public ------ |
이런 식으로 객체의 멤버 변수(필드) 하나하나의 정보를 담은 객체가 출력되는 걸 확인 할 수 있다.
Reflection
정의
Java에서 제공하는 표준 API로, 런타임에 클래스, 메서드, 필드, 생성자 등에 접근하고 조작할 수 있는 기능이다.
- 중요 포인트
- 컴파일 시점이 아니라 프로그램 실행 중(런타임)에 클래스의 구조를 읽고 조작
- 클래스 이름, 어노테이션, 메서드 시그니처 등을 문자열로 찾아 동적으로 로직 실행 가능
더보기
** 컴파일(Compile-time)과 런타임(Runtime) 차이
[소스코드] --(컴파일)--> [바이트코드(.class)] --(실행)--> [런타임: JVM 메모리 위에서 동작]
- 컴파일:
javac가 .java → .class(바이트코드)로 변환
문법 검사 + 타입 체크만 함
클래스가 실제로 실행되거나 메모리에 올라오진 않음
- 런타임:
java로 JVM이 .class를 읽어서 메모리에 로드
메서드 호출, 객체 생성, 변수 값 변경 등 실제 동작이 이루어짐
Reflection은 이 시점에서 클래스 정보를 읽어옴
코드로 보는 차이
<일반 호출(컴파일 시점에 확정)>
Person p = new Person(); // 컴파일러가 Person 클래스 존재 확인
p.sayHello(); // 메서드 존재 여부도 컴파일 시점에 체크됨
<Reflection 호출 (런타임에만 검사됨)>
Class<?> clazz = Class.forName("Person"); // 문자열 기반 → 컴파일러는 확인 못함
Object obj = clazz.getDeclaredConstructor().newInstance();
Method m = clazz.getMethod("sayHello"); // 없는 메서드면 여기서 런타임 예외
m.invoke(obj);
'공개 글' 카테고리의 다른 글
| 세션(Session), 쿠키(Cookie), 토큰(Token), JWT 완벽 정리 (0) | 2025.10.28 |
|---|---|
| Spring Batch(Tasklet)에서 트랜잭션 롤백(rollback)이 되지 않는 경우와 해결 방법 (1) | 2025.09.12 |
| static (2) | 2025.05.02 |
| 트랜잭션(Transaction) (0) | 2025.04.28 |
| JavaScript 기본 (1) | 2025.03.24 |