ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA] Reflection
    Language/Java 2020. 2. 1. 22:33

     

     

    자바의 특별한 기능 중 하나인 Reflection에 대해 알아보겠습니다.

     

     

    Reflection이란?

     

    리플렉션은 이미 로딩이 완료된 클래스에서 또 다른 클래스를 동적으로 로딩하여 생성자, 멤버 변수, 멤버 메소드 등을 사용할 수 있도록 하는 기능입니다.

    즉, 컴파일된 코드에서 역으로 클래스의 정보를 불러올 수 있고, 디컴파일 시에도 사용되는 기법입니다.

     

     

    사용법

    클래스 정보 가져오기

    Class myClass = Class.forName("클래스 이름");

    위 코드와 같이 forName() 메소드에 정보를 추출하고자 하는 클래스 이름을 파라미터로 넘겨 호출합니다.

    이제 이 클래스를 가지고 클래스 내부의 다양한 정보를 추출해낼 수 있습니다.

     

    Class myClass = Class.forName("클래스");  // 클래스 이름을 통해 클래스 가져오기
    Method[] methods = myClass.getDeclareMethods();  // 클래스 내부에 선언된 메소드들 가져오기
    
    for(Method method : methods) {
    	System.out.println(method.toString());  // 메소드 리스트 출력
    }

    반면 메소드도 이름을 알고 있다면 앞서 클래스 이름을 통해 클래스 정보를 가져온 것처럼 메소드 이름을 통해 메소드 정보를 가져올 수 있습니다. 

    Class myClass = Class forName("클래스 이름"); // 클래스 정보
    Method method = myClass.getMethod("setName", new Class[]{String.class});
    // 해당 클래스의 파라미터 타입이 String인 setName메소드
    method.invoke(myClass.newInstance(), new Object[]{new String("파라미터")});
    // setName메소드에 String타입 파라미터를 넘겨 호출

     

    invoke() 메소드를 통해 메소드를 호출할 때에는 위의 코드에서와 같이 파라미터를 넘겨줘야 합니다. 이때, 여러 개의 파라미터를 필요로 하는 메소드를 호출하는 경우에는 다음과 같은 방식을 사용합니다.

     

    Object[] intParamObject = new Object[] {1, 2}; // 파라미터 배열
    Method method = myClass.getMethod("sum", new Class[] {int.class, int.class}); // 메소드 정보 가져오기
    int sumResult = (int)method.invoke(test, intParamObject); // 파라미터 배열을 넘겨주어 메소드 호출

     

     

    이외의 메소드 관련 메소드

    System.out.println(method.getDeclaringClass()); // 해당 메소드가 선언된 클래스명
    System.out.println(method.getName()); // 메소드 이름
    System.out.println(method.getReturnType()); // 메소드의 리턴 타입
    System.out.pringln(method.getParameterTypes()); // 메소드의 파라미터 타입 리스트

     

    set(), get() 메소드를 통한 멤버 변수 값 변경

     

    Class myClass = Class.forName("Test"); // Test 클래스 가져오기
    
    Field field = myClass.getDeclaredField("myName"); // Test클래스 내, myName 변수 정보를 field에 저장
    field.setAccessible(true); // private일 경우 secAccessible(true)로 해줘야 접근 가능
    Test test = (Test)myClass.newInstance(); // myClass변수를 통해 Test클래스 객체 생성
    test.setMyName("Andy"); // setMyName() 메소드를 통해 myName변수에 "Andy"라는 값 할당
    
    System.out.println("Before Name : " + field.get(test)); // Field클래스의 get() 메소드를 이용해 
    														   myName변수 값 불러오기
    field.set(test, "Bob"); // Field클래스의 set() 메소드를 이용해 myName변수의 값 변경
    System.out.println("After Name : " + field.get(test));

     

     

    이러한 Reflection기법들은 컴파일 시점에서 에러를 검출하는 데에 한계가 있기 때문에, 실행 시 발생할 수 있는 에러에 대한 Exception처리가 필요합니다. 

    'Language > Java' 카테고리의 다른 글

    [Java] Java의 컬렉션 프레임워크  (0) 2020.04.19
    [JAVA] Enum이란?  (0) 2020.03.15
    [JAVA] Generic Type  (0) 2020.02.01
    [JAVA] Reader/Writer  (0) 2019.12.07
    [JAVA] InputStream/OutputStream  (0) 2019.12.07
Designed by Tistory.