반응형
리플렉션이란?
- 리플렉션이란 객체를 통해 클래스의 정보를 분석하는 기법
- 컴퓨터 프로그램에서 런타임 시점에 사용되는 자신의 구조와 행위를 관리(type introspection)하고 수정할 수 있는 프로세스를 의미한다.
자바 리플렉션 API (Class<T>)
- 자바 리플렉션 API는 Class<T> 객체로 부터 시작된다. 이 객체는 클래스 로딩 후에 힙(Heap) 영역에 저장된다.
- Class 타입의 인스턴스를 얻는 방법은 크게 3가지가 있다.
- 타입을 가지고 class 타입의 인스턴스를 가지고 오는 방법
Class<Book> bookClass = Book.class;
- 생성된 인스턴스를 가지고 class 타입의 인스턴스를 가지고 오는 방법
Book book = new Book(); Class<? extends Book> aClass = book.getClass();
- 클래스가 속한 패키지명을 모두 포함한 이름(FQCN, Fully Qualified Class Name)을 가지고 class 타입의 인스턴스를 가지고 오는 방법
- 클래스패스에 해당 클래스가 없다면 ClassNotFoundException이 발생한다.
Class<?> aClass1 = Class.forName("me.devhistory.Book");
Class 타입의 인스턴스로 클래스 정보를 얻을 수 있다.
Book.java
public class Book {
private static StringB= "BOOK";
private static final StringC= "BOOK";
private String a = "a";
public String d = "d";
protected String e = "e";
public Book() {
}
public Book(String a, String d, String e) {
this.a = a;
this.d = d;
this.e = e;
}
private void f(){
System.out.println("F");
}
public void g(){
System.out.println("g");
}
public int h(){
return 100;
}
}
MyBook.java
public class MyBook extends Book implements MyInterface{
}
App.java
public class App {
public static void main(String[] args) throws ClassNotFoundException {
Class<Book> bookClass = Book.class;
Book book = new Book();
Arrays.stream(bookClass.getFields()).forEach(System.out::println);
Arrays.stream(bookClass.getDeclaredFields()).forEach(System.out::println);
Arrays.stream(bookClass.getMethods()).forEach(System.out::println);
Arrays.stream(bookClass.getDeclaredConstructors()).forEach(System.out::println);
System.out.println(MyBook.class.getSuperclass());
Arrays.stream(MyBook.class.getInterfaces()).forEach(System.out::println);
Arrays.stream(Book.class.getDeclaredFields()).forEach(f -> {
int modifiers = f.getModifiers();
System.out.println(f);
System.out.println("\tPublic: "+Modifier.isPublic(modifiers));
System.out.println("\tProtected: "+Modifier.isProtected(modifiers));
System.out.println("\tPrivate: "+Modifier.isPrivate(modifiers));
System.out.println("\tStatic: "+Modifier.isStatic(modifiers));
});
}
}
- public 필드 정보 확인
Arrays.stream(bookClass.getFields()).forEach(System.out::println);
//public java.lang.String me.devhistory.Book.d
- 모든 필드 정보 확인
getDeclaredFields()
메소드 인자로 필드 이름을 주어 특정 필드만 가져오는 것도 가능하다.
Arrays.stream(bookClass.getDeclaredFields()).forEach(System.out::println);
//private static java.lang.String me.devhistory.Book.B
//private static final java.lang.String me.devhistory.Book.C
//private java.lang.String me.devhistory.Book.a
//public java.lang.String me.devhistory.Book.d
//protected java.lang.String me.devhistory.Book.e
- public 메소드 정보 확인
Arrays.stream(bookClass.getMethods()).forEach(System.out::println);
//public int me.devhistory.Book.h()
//public void me.devhistory.Book.g()
//public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
//public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
//public final void java.lang.Object.wait() throws java.lang.InterruptedException
//public boolean java.lang.Object.equals(java.lang.Object)
//public java.lang.String java.lang.Object.toString()
//public native int java.lang.Object.hashCode()
//public final native java.lang.Class java.lang.Object.getClass()
//public final native void java.lang.Object.notify()
//public final native void java.lang.Object.notifyAll()
- 생성자 정보 확인
Arrays.stream(bookClass.getDeclaredConstructors()).forEach(System.out::println);
//public me.devhistory.Book()
//public me.devhistory.Book(java.lang.String,java.lang.String,java.lang.String)
- 해당 클래스가 상속하는 부모 클래스 정보 확인
System.out.println(MyBook.class.getSuperclass());
//class me.devhistory.Book
- 해당 클래스가 구현하는 인터페이스 정보 확인
Arrays.stream(MyBook.class.getInterfaces()).forEach(System.out::println);
//interface me.devhistory.MyInterface
- 필드의 접근 수준지시자, Static 여부 등 정보 확인
Arrays.stream(Book.class.getDeclaredFields()).forEach(f -> {
int modifiers = f.getModifiers();
System.out.println(f);
System.out.println("\tPublic: "+Modifier.isPublic(modifiers));
System.out.println("\tProtected: "+Modifier.isProtected(modifiers));
System.out.println("\tPrivate: "+Modifier.isPrivate(modifiers));
System.out.println("\tStatic: "+Modifier.isStatic(modifiers));
});
//private static java.lang.String me.devhistory.Book.B
//Public: false
//Protected: false
//Private: true
//Static: true
//private static final java.lang.String me.devhistory.Book.C
//Public: false
//Protected: false
//Private: true
//Static: true
//private java.lang.String me.devhistory.Book.a
//Public: false
//Protected: false
//Private: true
//Static: false
//public java.lang.String me.devhistory.Book.d
//Public: true
//Protected: false
//Private: false
//Static: false
//protected java.lang.String me.devhistory.Book.e
//Public: false
//Protected: true
//Private: false
//Static: false
- 이 밖에도 메소드의 파라미터 타입, 파라미터 갯수, 리턴 타입, 제네릭 타입 등 클래스와 관련된 많은 정보를 확인할 수 있다.
[참고자료]
반응형
'Java > 기본' 카테고리의 다른 글
자바 리플렉션(Java Reflection) API - 클래스 정보 수정 및 실행 (0) | 2021.05.30 |
---|---|
자바 리플렉션(Java Reflection) API - 애노테이션 정보 조회 (0) | 2021.05.29 |
자바(Java) 바이트 코드 조작관련 - 자바 에이전트 (0) | 2021.05.29 |
자바(Java) 바이트 코드 조작관련 - ByteBuddy (0) | 2021.05.27 |
자바(Java) 바이트 코드 조작관련 - 코드 커버리지 (0) | 2021.05.26 |