Java Reflection의 정의

리플렉션이란 객체를 통해 클래스의 정보를 분석해내는 프로그램 기법을 말한다.

자바는 스크립트 언어가 아니라 컴파일언어이다.
물론 .java->.class-> 실행이라는 2단계의 매커니즘을 가지고 있다. 그러나 컴파일 언어로 분리하는게 옳다. 원래 자바에서는 동적으로 객체를 생성하는 기술이 없었다.
그리고 동적으로 인스턴스를 생성하는 Reflection으로 그 역할을 대신하게 된다.

*리플렉션이란 객체를 통해 클래스의 정보를 분석해 내는 프로그램 기법을 말한다.


가정을 해 보자. 만약 객체의 메모리만을 알고 있고, 그리고 객체의 형에 대해서는 모른다고 생각하보자, 
리플렉션으로 형은 알고 있지만 형변환을 할 수 없는 상태에서 객체의 메서드를 호출할 수 있다.


Class c = Data.class;
//Class c = Class.forName("클래스이름");

Method[] m = c.getMethods();                     
Field[] f = c.getFields();
Constructor[] cs = c.getConstructors();
Class[] inter = c.getInterfaces();
Class superClass = c.getSuperclass();




<Java Reflection의 사용>


Reflection은 자바의 특징이다. 실행중인 자바 프로그램 내부를 검사하고 내부의 속성을  수정할 수 있도록 한다. 예를들어, 어떤 자바 클래스가 가진 모든 멤버의 이름을 얻거나 보여줄 수 있다.
자바에서 클래스가 그 자신을 조사하고 수정하는 것이 많다고 할 수는 없으나 다른 언어에서는 볼 수 없는 특징이다.
reflection이 구체적인 쓰임중에 하나가 빌더툴을 이용해서 소프트웨어 컴포넌트를 만드는 곳에서 이다. 툴은 reflection을 사용해서 동적으로 로딩되는 자바 컴포넌트(클래스)의 속성을 얻을 수 있다.

예제)

import java.lang.reflect.Method

public class DumpMethods{
   public static void main(String args[]){
     try{
          Class c=Class.forName(args[0]);
          Method m[]=c.getDeclaredMethods();
          for(int i=0;i<m.length;i++){
               System.out.println(m[i].toString());
       }catch(Throwable e){
          System.err.pritln(e);
   }
}
}

명령
java DumpMethods java.util.Stack

실행 결과
  public java.lang.Object java.util.Stack.push(
    java.lang.Object)
   public synchronized
     java.lang.Object java.util.Stack.pop()
   public synchronized
      java.lang.Object java.util.Stack.peek()
   public boolean java.util.Stack.empty()
   public synchronized
     int java.util.Stack.search(java.lang.Object)

이 프로그램은 java.util.Stack 의 속성과 반환값에 따라 메소드리스트를 출력한다.
이 프로그램은 Class.forName 을 통해서 클래스를 로딩하고 getDeclaredMethods 을 통해서 클래스에서 정의한 메소드리스트를 얻는다. java.lang.reflect.Method  는 단일 메쏘드를 나타내는 클래스이다.





<Reflection을 사용한 Set up>

Method와 같은 reflection class는 java.lang.reflect에 있다. 이 클래스를 사용하기 위해서는 세 가지 스텝을 밟아야 한다.
첫 번째는 수정하기를 원하는 클래스의 java.lang.Class 객체를 얻어야 한ㄷ. java.lang.Class는 클래스를 표현하고, 실행중인 자바 프로그램과 인터페이스 한다.

*자바 기본형에 대한 클래스 정보를 얻는 방법
1. Class c=Class.forName("java.lang.String");

2. Class c=int.class;

3. 기본형의 경우 (Integer와 같은) Wrapper에 기정의된 TYPE을 사용한다.
   Class c=Integer.TYPE;



두 번째 스텝은, getDelcaredMethods와 같은 메소드를 Call해서, 클래스에 정의된 모든 메소드의 리스트를 얻는다.
세 번째 스텝은, 정보수정을 위해 Reflection API를 이용한다.

       Class c=Class.forName("java.lang.String");
       Method m[]=c.getDelcaredMethods();
       S.O.P(m[o].toString());



<Reflection을 사용한 Set up>

클래스 정보가 있으면, 다음 스텝은 클래스 객체에 대해서 기본적인 질의다. Class.isinstance 메소드는 instanceof를 통해서 구현될 수 있다.

class A{}

public class instance1{
   public static void main(String[] args){
        try{ 
                   Class cls=Class.forName("A");
                 
                   boolean b1=cls.isinstacne(new Integer(37));
                   S.O.P(b1);
           
                   boolean b2=cls.isinstance(new A());
                   S.O.P(b2);
          }catch(Throwable e){
            System.err.println(e);
     }
}
}


A의 클래스객체가 만들어진다. 그리고 class instance objects 가 A 의 인스턴스인지 체크한다. 
Integer(37) 은 아니지만, new A() 는 True 이다.


         
       

<Constructors에 대한 정보얻기>

import.java.lang.reflect.*

public class constructor1{
      public constructor1(){
      }

     protected constructor1(int i,double d){
     }

    public static void main(String args[]){
         try{
             Class cls=Class.forName("constructor1");

             Constructor ctolist[]=cls.getDeclaredConstructors();
             for(int i=0;i<ctolist.length;i++){
                 Constructor ct=ctorlist[i];
                 S.O.P("name="+ct.getName());
                 S.O.P("decl class="+ct.getDeclaringClass());
                 Class pvec[]=ct.getParameterTypes();

              for(int j=0;j<pvec.length;j++)
                  S.O.P("param#"+j+" "+pvec[j]);

            Class evec[]=ct.getExceptionTypes();

              for(int j=0;j<evec.length;j++)
                 S.O.P("exc #"+j+" "+evec[j]);


}}}


이 프로그램에서는 리턴타입정보가 없는데... 생성자는 리턴타입을 갖지 않기 때문이다.
실행결과
   name = constructor1
   decl class = class constructor1
   -----
   name = constructor1
   decl class = class constructor1
   param #0 int
   param #1 double







댓글

이 블로그의 인기 게시물

(18장) WebSocekt과 STOMP를 사용하여 메시징하기

(네트워크)폴링방식 vs 롱 폴링방식

(ElasticSearch) 결과에서 순서 정렬