
// Object.java
public final native Class<?> getClass();Object 클래스편 마지막으로 getClass()를 살펴보자.
Object 클래스 코드를 살펴보면 리턴타입이 Class 이다.
Class 클래스가 무엇일까?
Class 클래스 는 클래스와 인터페이스(Class, Interface, Enum, Annotation...)의 모든 정보를 담고있는 클래스이다.
클래스 당 1개만 존재하며, 클래스 로더에 의해서 메모리에 올라갈 때 힙 영역에 자동으로 생성된다.    
바로 코드로 이해해보자.
public class Book implements Readable {
    private String name;
    private int price;
    private int stock;
    public static final int OFF = 30;
    public Book(String name, int price) {
        this.name = name;
        this.price = price;
    }
    private boolean isSoldOut() {
        return this.stock < 0;
    }
    
    // getter, setter
    ...
}public static void main(String[] args) throws Exception {
    Book book = new Book("SPRING BOOK", 10000);
    Class<? extends Book> bookClass = book.getClass();
}간단하게 Book 클래스를 만들고, Object 클래스에서 상속받은 getClass() 를 호출했다.
위의 설명에서 Class 클래스는 클래스의 정보를 담고 있는 클래스라고 했다.   
그럼 Class 클래스로 어떤 일을 할 수 있는걸까 생각해보자.
모두 가능하다!
왜? Java Reflection API 기법을 사용하기 때문에 가능하다.
Reflection 이란?
구체적인 클래스 타입을 알지 못해도 그 클래스의 정보(메소드, 타입, 변수, ...)에
접근할 수 있게 해주는 자바 API 기법
Class<T>를 가지고 할 수 있는 것들은 다음과 같다.
예제를 통해 가볍게 Reflection을 사용해보자.
// 1.  클래스 리터럴(*.class)로 얻기
Class<Book> bookClass = Book.class;
// 2. 생성된 객체로 얻기
Book book = new Book("SPRING BOOK", 10000);
Class<? extends Book> bookClass2 = book.getClass();
// 3. 클래스 이름(FQCN)으로 얻기
Class<?> bookClass3 = Class.forName("com.jihan.javastudycode.lang.Book");Arrays.stream(bookClass.getDeclaredFields()).forEach(f -> {
    try {
        f.setAccessible(true);  //  true로 지정해야 private 접근가능
        System.out.printf("%s %s \n", f, f.get(book));
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
});private java.lang.String com.jihan.javastudycode.lang.Book.name SPRING BOOK 
private int com.jihan.javastudycode.lang.Book.price 10000 
private int com.jihan.javastudycode.lang.Book.stock 0 
public static final int com.jihan.javastudycode.lang.Book.OFF 30 getFields()를 할 경우 private 접근 제어자는 보이지 않음.
Arrays.stream(bookClass.getDeclaredMethods()).forEach(System.out::println);public java.lang.String com.jihan.javastudycode.lang.Book.getName()
public java.lang.String com.jihan.javastudycode.lang.Book.toString()
public void com.jihan.javastudycode.lang.Book.setName(java.lang.String)
public int com.jihan.javastudycode.lang.Book.getPrice()
public void com.jihan.javastudycode.lang.Book.setPrice(int)
public int com.jihan.javastudycode.lang.Book.getStock()
public void com.jihan.javastudycode.lang.Book.setStock(int)
private boolean com.jihan.javastudycode.lang.Book.isSoldOut()getMethods()를 할 경우 private 접근 제어자는 보이지 않음.
getMethods()를 할 경우 상속받은 메소드도 보여짐.
System.out.println(bookClass.getSuperclass());class java.lang.ObjectArrays.stream(bookClass.getInterfaces()).forEach(System.out::println);interface com.jihan.javastudycode.lang.ReadableConstructor<Book> constructor = bookClass.getConstructor(String.class, int.class);
Book theLordOfTheRings = constructor.newInstance("반지의 제왕", 20000);그런데 특별한 경우가 아닌 이상 애플리케이션 개발 시 Reflection을 자주 사용하는 일은 없을 것이다.
그렇다면 Reflection 기술은 주로 어디서 활용되고 있는걸까?   
다양한 프레임워크나 라이브러리 개발환경에서 많이 사용되는 기술이다.
또한 사용시 주의할 점이 몇 가지 있는데 강력한 기능인만큼 주의해서 쓰지 않으면 아래와 같이 문제가 발생할 수 있다.
https://docs.oracle.com/javase/tutorial/reflect/
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html
https://www.geeksforgeeks.org/reflection-in-java/
https://woowacourse.github.io/javable/post/2020-07-16-reflection-api/
https://www.inflearn.com/course/the-java-code-manipulation