[JAVA] Reflection

eunniverse·2024년 3월 3일
0
post-custom-banner
  • 정의

    • 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법
    • 힙 영역에 로드된 Class 타입의 객체를 통해 원하는 클래스의 인스턴스를 생성하도록 지원하고, 인스턴스의 필드와 메서드를 접근 제어자와 상관없이 사용할 수 있도록 지원하는 API
  • 특징

    • JAVA 의 특징이다.
    • 런타임에 클래스를 분석하므로 속도가 느리다.
    • 런타임 시점에서 인스턴스를 생성하므로 컴파일 시점에서 타입체크가 불가능하다.
    • JVM에서 클래스 정보를 클래스 로더를 통해 읽어와서 해당 정보를 메모리에 저장하며, 이 정보를 기반으로 리플렉션을 사용할 수 있다.
  • 장점

    • 확장성 - 재사용 가능한 컴포넌트로 만들 수 있다.
    • class 브라우저 및 시각적 개발 환경을 제공한다.
  • 사용 방법

    • 힙영역에 로드된 클래스 타입의 객체를 가져와야 한다.
      1 .class 확인
      2 인스턴스.getClass() 확인
      3 Class.forName(’클래스명’) 확인

      @Test
      public void getClassInfo() throws ClassNotFoundException {
          // 1번 방법
      		Class animalClass = Animal.class; 
      
      		// 2번 방법
          Animal animal = new Dog("happy");
          animalClass = animal.getClass();
      
      		// 3번 방법
          animalClass = Class.forName("test.reflection.Animal");
      }
    • getXXX() vs getDelcaredXXX()

      • getXXX() - 상속받은 클래스와 인터페이스를 포함하여 모든 public 요소를 가져온다.
      • getDeclaredXXX() - 상속받은 클래스와 인터페이스를 제외하고 해당 클래스에 직접 정의된 내용만 가져온다.
  • Constructor 타입

    • 정의
      - java.lang.reflect 패키지에서 제공하는 클래스
      - 클래스 생성자에 대한 정보와 접근을 제공

      // 생성자 가져오기
      Constructor<?> constructor = aClass.getDeclaredConstructor();
      Member member = (Member) constructor.newInstance();
      
      // 생성자에 파라미터가 있을 경우, 대응하는 타입을 전달하면 됨
      Constructor<?> noArgsConstructor = aClass.getDeclaredConstructor();
      Constructor<?> onlyNameConstructor = aClass.getDeclaredConstructor(String.class);
      
      // private 생성자일 경우 setAccessible 사용
      Constructor<?> allArgsConstructor = aClass.getDeclaredConstructor(String.class, int.class);
      allArgsConstructor.setAccessible(true);
      Member member = (Member) allArgsConstructor.newInstance();
  • Field 타입
    • 정의
      • 클래스의 필드(멤버변수) 정보를 얻어오는 방법

        Dog dog = new Dog("happy");
        Class clazz = dog.getClass();
        
        // 모든 접근가능한 필드 가져오기
        Field[] fields = clazz.getFields();
        
        // 클래스에 정의되어 있는 모든 필드 가져오기
        Field[] allFields = clazz.getDeclaredFields();
        
        // 이름으로 필드 가져오기
        // 잘못된 이름으로 찾을 경우 NoSuchFieldException 발생됨
        Field ageField = clazz.getField("age");
  • Method 타입
    • 정의
      • 클래스에 정의되어 있는 메서드 정보를 얻어오는 방법

        Class clazz = Class.forName("test.Person");
        
        // 이름으로 메소드 정보 가져오기
        Method method1 = clazz.getDeclaredMethod("getAge");
        
        // 이름과 인자 타입으로 메소드 정보 가져오기
        Method method2 = clazz.getDeclaredMethod("setName", String.class);
        
        // 인자가 없는 메소드 가져오기
        Method method3 = clazz.getDeclaredMethod("methodName", null);
        
        // 모든 메소드 가져오기
        Method[] methods1 = clazz.getDeclaredMethods();
        
        // Public 메소드 가져오기 (본 클래스와 부모 클래스)
        Method[] methods2 = clazz.getMethods();
        
        // person 객체에서 method 호출
        Method method = clazz.getMethod("getAge");
        method.invoke(person);
        
        // 파라미터를 담은 메서드 호출
        personClass.getDeclaredMethod("setAge", int.class).invoke(person, 20);
        personClass.getDeclaredMethod("getAge").invoke(person);
    • 특징
      • getMethods() 는 해당 클래스와 부모 클래스에 정의되어 있는 public 클래스를 가져오고, getDeclaredMethod() 는 private 메서드 정보 또한 접근할 수 있다.
      • invoke() 메서드를 통해 동적으로 메서드를 호출 할 수 있다.
profile
능력이 없는 것을 두려워 말고, 끈기 없는 것을 두려워하라
post-custom-banner

0개의 댓글