Skip to content

Latest commit

 

History

History
101 lines (86 loc) · 4.13 KB

조윤호.md

File metadata and controls

101 lines (86 loc) · 4.13 KB

[JAVA] 리플렉션 - 조윤호

Class 클래스

  • java.lang.Class
  • 클래스에 대한 메타데이터 관리
    • 어노테이션
    • 클래스 생성자
    • 클래스 필드
    • 클래스 메서드
    • 부모 클래스, 구현 인터페이스 조회

클레스 데이터 - JVM 메모리 > 메소드 영역 인스턴스 정보 - JVM 메모리 > 힙 영역

Class 인스턴스

  • public 생성자 없음
  • JVM에 의해 자동 생성됨
  • 다음 방법으로 인스턴스를 가져올 수 있음
Class<?> c = MyCsStudy.class;
Class<?> c = myCsStudy.getClass();
Class<?> c = Class.forName("org.....MyCsStudy");

.getMethods : 상속한 메서드를 포함, 모든 public 메서드 가져옴 .getDeclaredMethods : 직접 클래스에서 선언한 모든(pub,pri,protected 모두) 메서드 가져옴

Class<?> classInstanceOfClassClass = Class.class;
System.out.println("classInstanceOfClassClass.getDeclaredMethods() = "
        + Arrays.toString(classInstanceOfClassClass.getDeclaredMethods()));

classInstanceOfClassClass.getDeclaredMethods() =
[
    public java.lang.String java.lang.Class.getName(),
    private void java.lang.Class.checkPackageAccess(java.lang.SecurityManager,java.lang.ClassLoader,boolean),
    public static java.lang.Class java.lang.Class.forName(java.lang.String,boolean,java.lang.ClassLoader) throws java.lang.ClassNotFoundException,
    public static java.lang.Class java.lang.Class.forName(java.lang.String) throws java.lang.ClassNotFoundException,
    public static java.lang.Class java.lang.Class.forName(java.lang.Module,java.lang.String),
    private static native java.lang.Class java.lang.Class.forName0(java.lang.String,boolean,java.lang.ClassLoader,java.lang.Class) throws java.lang.ClassNotFoundException,
    public java.lang.String java.lang.Class.toString(),
    public java.lang.Module java.lang.Class.getModule(),
    public java.security.ProtectionDomain java.lang.Class.getProtectionDomain(),
    public native boolean java.lang.Class.isAssignableFrom(java.lang.Class),
    public native boolean java.lang.Class.isInstance(java.lang.Object),
    public native int java.lang.Class.getModifiers(),
 
    // ...
]

Constructor

  • Class 객체 -> Constructor 객체 -> .newInstance()
  • .getDeclaredConstructors();, .getConstructors();, .getDeclaredConstructor();, .getConstructor();
  • private 생성자인 경우, constructor.setAccessible(true); 설정하여 접근 가능
Constructor<?> publicConstructor = child.getDeclaredConstructor();
// privateConstructor.setAccessible(true);
publicConstructor.newInstance();

Field

  • Field객체를 통해 접근 가능 (.getDeclaredFields();, .getFields();, .getDeclaredField();, .getField();)
  • private 필드인 경우, .setAccessible(true);설정하여 접근
  • .get(...), .set(...) -> 조회/수정
Field[] fields = child.getDeclaredFields();
Field field = child.getField("value");

Method

  • Method 객체를 통해 접근 가능 (.getDeclaredMethods();, .getMethods();, .getDeclaredMethod();, .getMethod();)
  • private 필드인 경우, .setAccessible(true);설정하여 접근
  • .invoke(...) -> 실행

Annotation

  • .getDeclaredAnnotations(), .getDeclaredAnnotations()
  • 어노테이션이 붙어있는지 확인 후 로직 수행

리플렉션

  • 컴파일 시점까지 클래스,객체의 정보를 알 수 없는 경우
  • 프레임워크
  • 라이브러리
  • 어노테이션

단점

  1. 일반 메서드 호출보다 성능이 떨어짐
    컴파일 시점이 아니라 런타임 시점에서 클래스를 분석하기 때문
    JVM 최적화 불가
  2. 컴파일 시점에서 타입 체크 기능을 사용할 수 없다.
  3. 코드가 지저분하고 장황해짐
  4. 런타임 에러가 매우 많이 발생한다.
  5. 내부 노출, 추상화가 파괴됨, 불변성 보장 x

필요한 경우

  • 런타임에 존재하지 않을 수도 있는 클래스,메서드,필드와의 의존성 관리
  • 버전이 여러 개 있는 외부 패키지
    가장 오래된 버전으로 컴파일 -> 이후 버전의 클래스는 리플렉션으로 접근
  • 등등, 꼭 필요할때만 쓰자
  • (이펙티브 자바 ch.65 참고)