참고
java.lang.Class - reflect
NOTE
자바의 Class 클래스는 클래스의 정보(메타 데이터)를 다루는 리플렉션의 기반이며, 런타임에 클래스의 메타데이터에 접근하고 조작할 수 있습니다. 이를 통해 동적으로 객체를 생성하고 메서드를 호출하는 고급 기능을 제공합니다.
public static void main(String[] args) throws Exception{
// 클래스 불러오기
Class clazz = String.class;
Class clazz1 = new String().getClass();
Class<?> clazz2 = Class.forName("java.lang.String");
// 생성자 정보 얻기
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("constructor = " + constructor);
Class[] parameterTypes = constructor.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println("parameterType = " + parameterType);
}
}
// 필드 정보 얻기
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("field = " + field.getType() + " " + field.getName());
}
// 메서드 정보 얻기(전체 혹은 하나를 가져올 수 있다.)
Method[] declaredMethods = clazz.getDeclaredMethods();
Method declaredMethod = clazz.getDeclaredMethod("toString");
for (Method method : declaredMethods) {
System.out.println("method = " + method);
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println("parameter = " + parameter);
}
}
System.out.println("declaredMethod = " + declaredMethod);
// 슈퍼 클래스 정보 얻기
System.out.println("SuperClass " + clazz.getSuperclass().getName());
// 구현 인터페이스 정보 얻기
Class[] interfaces = clazz.getInterfaces();
for (Class i : interfaces) {
System.out.println("i = " + i);
}
}
Java
복사
class 예제코드(더 많은 메서드들이 있다.)
•
타입 정보 얻기: 클래스의 이름, 슈퍼 클래스, 인터페이스, 접근 제한자 등과 같은 정보를 조회할 수 있습니다.
•
리플렉션: 클래스에 정의된 메서드 필드, 생성자 등을 조회하고, 이들을 통해 객체 인스턴스를 생성하거나 메서드를 호출하는 등의 작업을 할 수 있습니다.
•
동적 로딩과 생성: Class.forName() 메서드를 사용해 클래스를 동적으로 로드하고, newInstance()메서드를 통해 생성할 수 있습니다.
•
애노테이션 처리: 클래스에 적용된 애노테이션을 조회하고 처리하는 기능을 제공합니다.
Class 리플렉션
NOTE
Class 클래스에는 클래스의 모든 정보가 들어 있습니다. 이 정보를 기반으로 인스턴스를 생성하거나, 메서드를 호출하고, 필드의 값을 변경할 수 있습니다.
public class Hello {
public String message = "hello";
public String hello(){
return message;
}
}
Java
복사
예제 클래스
public static void main(String[] args) throws Exception{
// 클래스 정보를 가져온다.
Class helloClass = Hello.class;
Class helloClass2 = Class.forName("lang.clazz.Hello");
// Hello 클래스의 인스턴스 생성
Hello hello = (Hello) helloClass.getDeclaredConstructor().newInstance();
// hello 메서드 호출
String result = hello.hello();
System.out.println("result = " + result);
Field message = helloClass.getDeclaredField("message"); // 필드 접근
message.setAccessible(true); // private 필드 접근 가능하게 설정
message.set(hello, "Hello, Reflection!");
// 변경된 필드 값을 사용하여 메서드 호출
String updatedResult = hello.hello();
System.out.println("updatedResult = " + updatedResult);
// 동적으로 메서드 호출하기
Method helloMethod = helloClass.getDeclaredMethod("hello");
String dynamicResult = (String) helloMethod.invoke(hello);
System.out.println("dynamicResult = " + dynamicResult);
}
Java
복사
리플렉션 예제
어노테이션
NOTE
자바 어노테이션은 코드에 메타데이터를 추가하는 방법을 제공합니다. 이는 코드 작성 방식, 컴파일/런타임 시 처리 정보, 그리고 리플렉션을 통해 사용 가능한 구성 데이터를 제공합니다.
// 메소드가 슈퍼클래스의 메소드를 오버라이드한다는 것을 나타냅니다.
@Override
// 메소드나 클래스가 더 이상 사용되지 않으멀로 사용을 지양해야 한다는 것을 나타냅니다.
@Deprecated
// 컴파일러 경고를 무시하도록 지시합니다.
@SuppressWarnings
// 제네릭 타입의 가변 인자 메소드에 대한 경고를 무시하도록 지시합니다.
@SafeVarargs
// 인터페이스가 함수형 인터페이스임을 나타냅니다.
@FunctionalInterface
Java
복사
표준 어노테이션
•
컴파일러에 대한 지시어: 특정 경고를 무시하도록 지시하는 등 컴파일러에 대한 정보를 제공합니다.
•
컴파일 시간 및 배포시간 처리: 소스 코드를 자동으로 생성하거나 XML 파일을 자동으로 생성하는 작업을 수행합니다.
•
런타임 처리: 실행 시간에 어노테이션을 사용하여 특정 동작을 구성하거나 실행합니다.
메타 어노테이션
NOTE
메타 어노테이션은 사용자 정의 어노테이션을 생성할 때 사용되는 어노테이션입니다. 주로 어노테이션의 동작을 정의하는데 사용됩니다.
// 어노테이션이 적용될 수 있는 요소(메소드, 필드)
@Target({
ElementType.TYPE,
ElementType.FIELD,
ElementType.METHOD,
ElementType.LOCAL_VARIABLE,
ElementType.PARAMETER,
})
// 어노테이션의 정보가 어느 시점까지 유효한지(소스, 클래스, 런타임)
@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.RUNTIME)
// 어노테이션 정보가 문서에 포함될지
@Documented
// 어노테이션이 자식 클래스에 상속 가능한지
@Inherited
// 같은 어노테이션을 한 요소에 여러 번 적용할 수 있도록 한다.
@Repeatable
Java
복사
메타 어노테이션 예제
// 마커 어노테이션 - 인자값 없음
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMarkerAnnotation {}
// 일반 어노테이션 - 인자값 있음
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Task {
String description() default "No description"; // 작업 설명
int priority() default 0; // 작업 우선순위
}
Java
복사
사용자 정의 어노테이션 예제
•
사용자 정의 어노테이션은 @interface로 생성할 수 있습니다.
리플렉션과 어노테이션의 조합
NOTE
리플렉션과 어노테이션을 조합해서 런타임에 클래스, 메소드, 필드 등의 정보를 조사하고 수정할 수 있는 기능을 제공할 수 있습니다.
// 사용자 정의 어노테이션 정의
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String description();
}
Java
복사
사용자 정의 어노테이션
public class MyApplication {
// 어노테이션 적용
@MyAnnotation(description = "This method adds two numbers")
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) throws Exception {
// 메소드 검색
Method method = MyApplication.class.getMethod("add", int.class, int.class);
// 어노테이션 적용여부
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
System.out.println("Description: " + annotation.description());
int result = (Integer) method.invoke(new MyApplication(), 5, 3);
System.out.println("Result: " + result);
}
}
}
Java
복사
@MyAnnotation 리플렉션 예제