728x90
인프런에 있는 백기선님의 더 자바, 코드를 조작하는 다양한 방법 을 보고 정리하는 글입니다.
리플렉션
리플렉션으로 알아볼 수 있는 것들
일단 maven 프로젝트를 생성한다.
App 클래스가 있는 패키지 경로에 Book을 생성.
Book에 접근제한자를 다양하게 선언해본다.
Book.java
public class Book {
private static String B = "BOOK";
private static final String C = "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;
}
}
이제 Book에 어떤 필드, 어떤 메소드 등이 쓰였는지 확인 하기 위해 Class라는 api를 사용한다.
어떠한 클래스의 정보를 가져오는 방법
- 클래스의 인스턴스를 가져오는 방법
// Book.class
Class<Book> bookClass = Book.class;
// FQCN (Fully Qualified Class Name) 만 알 때
Class<?> aClass1 = Class.forName("me.whiteship.Book");
- 필드를 가져오고 싶을 때
Field[] fields = bookClass.getFields();
//public 한 것만 가져오고 싶은 경우
Array.stream(bookClass.getFields()).forEach(System.out::println);
//접근 제한자 상관 없이 가져오는 경우
Book book = new Book(); // Book 클래스 선언
Array.stream(bookClass.getDeclaredFields()).forEach(f-> {
try {
f.setAccessible(true);// 무조건 접근 가능하게 하려면
System.out.printf("%s %s\n",f,f.get(book));; // 이것만 사용하는 경우에는 Error 접근 불가능한 것에 접근하기 때문
} catch (IllegalAccessException e) {
e.printStackTrace();
}
})
- 메소드를 가져올 때
//Object를 상속하는 것도 가져온다.
Arrays.stream(bookClass.getMethods()).forEach(System.out::println);
// 메소드가 public인지 private 인지 static인지 알아볼때
Arrays.stream(Book.class.getDeclaredFields()).forEach(f->{
int modifiers = f.getModifiers();
System.out.println(f);
System.out.println(Modifier.isPrivate(modifiers));
System.out.println(Modifier.isStatic(modifiers));
});
- 생성자
Arrays.stream(bookClass.getDeclaredConstructors()).forEach(System.out::println);
- 상위 클래스(super class)
System.out.println(MyBook.class.getSuperclass()); // 상위 클래스는 1개이므로 배열로 가져올 수 없다.
- 인터페이스
Arrays.stream(MyBook.class.getInterfaces()).forEach(System.out::println);
- 어노테이션
Arrays.stream(Book.class.getAnnotations()).forEach(System.out::println); // 이렇게 하면 정보가 나오지 않는다.
7번의 어노테이션 정보가 나오지 않는 이유는 어노테이션은 기본적으로 주석으로 인식하기 때문이다.
하지만 바이트코드에는 남지만 바이트 코드를 로딩했을 때 주석이라고 인식하여 메모리 상에는 남지 않는다.
같이 읽어오고 싶으면 어노테이션에다가 @Retention(RetentionPolicy.RUNTIME) 을 해준다.
확인하는 방법
- @Annotation 생성
MyAnnotation
Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
@Inherited //상속이 되는 어노테이션이다 라는 뜻
public @interface MyAnnotation {
String name() default "yeonsang";
// String value() default "yeonsang";
int number() default 100;
}
- 어노테이션 사용
Book.java
@MyAnnotation
public class Book{...}
- javap 명령어 사용
/target/classes 에서 해당 어노테이션이 사용된 클래스 경로를 복사 한 뒤에 터미널에서javap -c -v 복사한 경로
출처 : 더 자바 , 코드를 조작하는 다양한 방법
728x90
'더 자바' 카테고리의 다른 글
더 자바 리플렉션(2) (0) | 2022.04.04 |
---|---|
더 자바 바이트코드 조작 (0) | 2022.03.31 |
더 자바 JVM (0) | 2022.03.31 |
Comment