[Java] Reflection, Class 객체

호호빵·약 13시간 전
0

Java

목록 보기
19/19

Class 객체

package java.lang

public final class Class<T> implements Serializable, GenericDeclaration, Type, AnnotatedElement {

	private final ClassLoader classLoader;

 	private Class(ClassLoader loader) {
    	classLoader = loader;
    }


}

Instances of the class Class represent classes and interfaces in a running Java application.
An enum class and a record class are kinds of class; an annotation interface is a kind of interface.
Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions.
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.

Class has no public constructor. Instead a Class object is constructed automatically by the Java Virtual Machine when a class is derived from the bytes of a class file through the invocation of one of the following methods:

  • java에서 클래스와 인터페이스는 런타임 중에 Class 객체로 표현됨
    즉, 모든 클래스와 인터페이스는 Class 객체를 통해 메타데이터를 제공
    • enum, record, annotation 도 Class 객체로 표현됨
    • 모든 배열도 내부적으로 Class 객체를 공유 (같은 타입과 차원을 가지면 동일한 Class 객체 공유)
    • 기본 타입(Primitive Type)도 Class 객체로 표현됨 (int, double, boolean 등)
  • 생성자를 통해 만들 수 없고 JVM이 자동으로 생성해 줌
  • 리플렉션이나 동적 클래스 생성에서 사용될 수 있음


Reflection

  • Java에서 런타임 중에 클래스, 메서드, 필드 등을 조사하고 조작할 수 있는 기능
  • 컴파일 시점이 아니라 실행 시점(Run-time)에 클래스 정보를 가져오거나 수정 가능
  • Class 객체 사용
    • 클래스 정보 가져오기
    • 객체 동적 생성하기
    • 메서드 실행하기
    • 필드 값 읽기/수정하기

1. 클래스 정보 가져오기

  • 예시
class Person {
    private String name;
    public int age;

    public Person() {}

    public void sayHello() {
        System.out.println("Hello!");
    }
}

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // ① Class 객체 얻기 (3가지 방법)
            Class<?> clazz1 = Person.class;  // 정적 방식
            Class<?> clazz2 = new Person().getClass(); // 인스턴스를 통해 얻기
            Class<?> clazz3 = Class.forName("Person"); // 문자열을 통해 얻기

            // ② 클래스의 필드 목록 가져오기
            Field[] fields = clazz1.getDeclaredFields();
            System.out.println("Fields:");
            for (Field field : fields) {
                System.out.println("- " + field.getName());
            }

            // ③ 클래스의 메서드 목록 가져오기
            Method[] methods = clazz1.getDeclaredMethods();
            System.out.println("\nMethods:");
            for (Method method : methods) {
                System.out.println("- " + method.getName());
            }

            // ④ 클래스의 생성자 목록 가져오기
            Constructor<?>[] constructors = clazz1.getConstructors();
            System.out.println("\nConstructors:");
            for (Constructor<?> constructor : constructors) {
                System.out.println("- " + constructor.getName());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 활용

  • 프레임워크(Spring, Hibernate 등)
    → @Autowired 같은 기능은 리플렉션을 사용해 동적으로 의존성을 주입함.
  • JSON 직렬화/역직렬화
    → Jackson, Gson 같은 라이브러리는 리플렉션을 사용해 필드 값을 자동으로 변환함.
  • 테스트 프레임워크(JUnit)
    → @Test 메서드를 찾아 실행하는 것도 리플렉션을 이용함.

3. 단점

  • 성능 저하
    → 일반적인 new보다 객체 생성이 느림.
  • 보안 문제
    → private 필드까지 접근할 수 있어서 보안 취약점이 발생할 가능성이 있음.
  • 코드 가독성 저하
    → 일반 코드보다 복잡하고, 유지보수가 어려움.
  • 그래서 필요할 때만 최소한으로 사용하자!



reference

https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/lang/Class.html

profile
하루에 한 개념씩

0개의 댓글

관련 채용 정보