구체적인 클래스 타입을 알지 못해도 해당 클래스의 객체 생성, 메소드, 타입, 변수들에 접근할 수 있도록 도와주는 Java API
리플렉션의 시작 - Class
Class에 접근하는 방법
모든 클래스를 로딩 한 다음 Class의 인스턴스가 생긴다.(클래스 로더는 .class를 읽고 메서드 메모리에 저장한 다음, class 타입의 객체를 생성해 힙 영역에 저장한다) "타입.class"로 접근 가능
예) Class bookClass = Book.class;
모든 인스턴스는 getclass() 메소드를 가지고 있음. "인스턴스.getClass()"로 접근 가능
예) Book book = new book;
Class<? extends Book> aClass = book.getClass();
클래스를 문자열로 읽어오는 방법
예) Class<?> aClass1 = Class.forName("me.alwayslee.Book");
Class를 통해 할 수 있는 것
필드(목록) 가져오기(getModifiers()를 이용해 public, private, protective 확인 가능)
ex) Arrays.stream(bookClass.getFields()).forEach(System.out::println);
getFields() (public만) -> getDeclearedFields() 하면 모든 필드 가져옴.
또한, setAccessible(true)로 하면 접근이 불가능한 필드도 접근이 가능하게 되어 필드의 값을 확인할 수 있음
메소드(목록) 가져오기
ex) Arrays.stream(bookClass.getMethods()).forEach(System.out::println);
상위 클래스 가져오기
ex) System.out.println(bookClass.getSuperclass())
인터페이스(목록) 가져오기
ex) Arrays.stream(MyBook.class.getInterfaces()).forEach(System.out::println);
애노테이션 가져오기
생성자 가져오기
ex) Arrays.stream(bookClass.getDeclaredConstructors()).forEach(System.out::println);
Class 인스턴스 만들기
Class.newInstance()는 deprecated 되었으니 생성자를 통해 만들어야 한다
Class<?> bookClass = Class.forName("me.alwayslee.Book");
Constructor<?> constructor = bookClass.getConstructor(String.class);
Book book = (Book) constructor.newInstance("myBook");
필드 값 접근하기/설정하기
특정 인스턴스가 가지고 있는 값을 가져오는 것이기에 인스턴스 필요
Field a = Book.class.getDeclaredField("A");
a.set(null,"AAA");
null을 넣은 이유는 Static한 A가 Static한 필드이기 때문이다.(Static 필드는 Object가 없어도 되니 null을 넘긴다)
메소드 실행하기
Method b = Book.class.getDaclaredMethod("sum", int.class, int.class);
b.invoke(book, 1, 2);
중요 애노테이션
리플렉션
리플렉션 사용시 주의할 것
스프링
하이버네이트
JUnit
참고