자바 반사 메커니즘(1)

Java 반사 메커니즘 소개:
 
자바 가 실 행 될 때 환경 에서 임의의 클래스 에 대해 어떤 속성 과 방법 이 있 는 지 알 수 있 습 니까?임의의 대상 에 대해 그것 의 임의의 방법 을 호출 할 수 있 습 니까?답 은 긍정 적 이다.이러한 동적 획득 류 의 정보 와 동적 호출 대상 의 방법 은 자바 언어의 반사 에서 나온다.
 
  1.실행 할 때 임의의 대상 이 속 한 종 류 를 판단 합 니 다.
  2.운행 할 때 임의의 유형의 대상 을 구성한다.
  3.실행 할 때 임의의 클래스 가 가지 고 있 는 구성원 변수 와 방법 을 판단 합 니 다.
  4.실행 할 때 임의의 대상 을 호출 하 는 방법
 
  일반적으로 개발 자 커 뮤 니 티 는 동적 언어 에 대해 대체적으로 인정 하 는 정 의 는'프로그램 이 실 행 될 때 프로그램 구조 나 변수 유형 을 바 꿀 수 있 고 이런 언어 를 동적 언어 라 고 부른다'는 것 이다.이 관점 에서 볼 때 Perl,Python,Ruby 는 동적 언어 입 니 다.C+,자바,C\#동적 언어 가 아 닙 니 다.
 
  JDK 에서 주로 다음 과 같은 종류 로 자바 반사 메커니즘 을 실현 하 는데 이런 종 류 는 모두 java.lang.reflect 패키지 에 있다
  
   1.Class 류:한 종 류 를 대표 합 니 다.내부 류
   2.Field 클래스:대표 클래스 의 구성원 변수(구성원 변 수 는 클래스 의 속성 이 라 고도 함).
   3.Method 류:대표 적 인 방법.
   4.Constructor 류:대표 적 인 구조 방법.
   5.Array 클래스:동적 으로 배열 을 만 들 고 배열 에 접근 하 는 요 소 를 정적 으로 만 드 는 방법 을 제공 합 니 다.
Reflection API 의 기본 작
예 1:
 

public class DumpMethods
{
    public static void main(String args[]) throws Exception
    {
        //                
        Class<?> classType = Class.forName(args[0]);
        //         
        Method methods[] = classType.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++)
        {
            System.out.println(methods[i].toString());
        }
    }
}



ReflectTester 클래스 의 copy(Object object)방법 은 다음 절 차 를 순서대로 수행 합 니 다.
  (1)획득 대상 의 유형:
        Class classType=object.getClass();
       System.out.println("Class:"+classType.getName());
 
자바.lang.Object 클래스 에서 getClass()방법 을 정 의 했 기 때문에 임의의 자바 대상 에 대해 서 는 이 방법 을 통 해 대상 의 유형 을 얻 을 수 있 습 니 다.Class 클래스 는 Reflection API 의 핵심 클래스 입 니 다.getName():클래스 의 전체 이름 을 얻 는 방법 이 있 습 니 다.
  getFields():클래스 의 Public 형식의 속성 을 얻 습 니 다.
  getDeclared Fields():클래스 의 모든 속성 을 획득 합 니 다.
  getMethods():클래스 의 Public 형식 을 얻 는 방법 입 니 다.
  getDeclared Methods():클래스 를 얻 는 모든 방법.
  getMethod(String name,Class[]parameterTypes):클래스 를 얻 는 특정한 방법,getMethod(String name,Class[]   parameterTypes):클래스 의 특정한 방법,name 매개 변수 지정 방법의 이름,parameterTypes 매개 변수 지정 방법의 매개 변수 유형 을 얻 습 니 다.
   getConstructors():클래스 의 Public 유형의 구조 방법 을 얻 습 니 다.
  getConstructor(Class[]parameterTypes):클래스 의 특정 구조 방법 을 얻 고 parameterTypes 매개 변 수 는 구조 방법의 매개 변수 유형 을 지정 합 니 다.
   new Instance():클래스 의 매개 변수 가 없 는 구조 방법 으로 이러한 대상 을 만 듭 니 다.
(2)기본 구조 방법 으로 새 대상 만 들 기:
      Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
      상기 코드 는 먼저 Class 류 의 getConstructor()방법 을 호출 하여 Constructor 대상 을 얻 었 습 니 다.이것 은 기본 적 인 구조 방법 을 대표 한 다음 에 호출 합 니 다.    Constructor 대상 의 new Instance()방법 은 인 스 턴 스 를 구성 합 니 다.
(3)획득 대상 의 모든 속성:
      Field fields[]=classType.getDeclaredFields();
     Class 클래스 의 getDeclared Fields()방법 은 클래스 의 모든 속성 을 되 돌려 줍 니 다.Public,proctected,기본 값 과 private 접근 등급 의 속성 을 포함 합 니 다.
(4)각 속성 에 해당 하 는 getXXX()와 setXXX()방법 을 획득 한 후 이 방법 을 실행 하여 원래 대상 의 속성 을 새로운 대상 에 복사 합 니 다.
예 코드 는 다음 과 같 습 니 다.

 public class ReflectTester
{
    public Object copy(Object object) throws Exception
    {
        //        
        Class<?> classType = object.getClass();
        System.out.println("Class:" + classType.getName());

        //                 
        Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});

        //          
        Field fields[] = classType.getDeclaredFields();

        for (int i = 0; i < fields.length; i++)
        {
            Field field = fields[i];

            String fieldName = field.getName();
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            //         getXXX()     
            String getMethodName = "get" + firstLetter + fieldName.substring(1);
            //         setXXX()     
            String setMethodName = "set" + firstLetter + fieldName.substring(1);

            //         getXXX()  
            Method getMethod = classType.getMethod(getMethodName, new Class[] {});
            //         setXXX()  
            Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });

            //       getXXX()  
            Object value = getMethod.invoke(object, new Object[] {});
            System.out.println(fieldName + ":" + value);
            //        setXXX()  
            setMethod.invoke(objectCopy, new Object[] { value });
        }
        return objectCopy;
    }

    public static void main(String[] args) throws Exception
    {
        Customer customer = new Customer("Tom", 21);
        customer.setId(new Long(1));

        Customer customerCopy = (Customer) new ReflectTester().copy(customer);
        System.out.println("Copy information:" + customerCopy.getId() + " " + customerCopy.getName() + " "
                + customerCopy.getAge());
    }
}

class Customer
{
    private Long id;

    private String name;

    private int age;

    public Customer()
    {
    }

    public Customer(String name, int age)
    {
        this.name = name;
        this.age = age;
    }

    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getAge()
    {
        return age;
    }

    public void setAge(int age)
    {
        this.age = age;
    }
}

반사 체 제 를 이용 하여 InvokeTester 대상 의 add()와 echo()방법 을 호출 합 니 다.
예 3:

public class InvokeTester
{
    public int add(int param1, int param2)
    {
        return param1 + param2;
    }

    public String echo(String msg)
    {
        return "echo: " + msg;
    }

    public static void main(String[] args) throws Exception
    {
        Class<?> classType = InvokeTester.class;
        Object invokeTester = classType.newInstance();

        // Object invokeTester = classType.getConstructor(new
        // Class[]{}).newInstance(new Object[]{});

        //   InvokeTester   add()  
        Method addMethod = classType.getMethod("add", new Class[] { int.class, int.class });
        Object result = addMethod.invoke(invokeTester, new Object[] { new Integer(100), new Integer(200) });
        System.out.println((Integer) result);

        //   InvokeTester   echo()  
        Method echoMethod = classType.getMethod("echo", new Class[] { String.class });
        result = echoMethod.invoke(invokeTester, new Object[] { "Hello" });
        System.out.println((String) result);
    }
}

add()방법의 두 매개 변 수 는 int 형식 입 니 다.add()방법 을 나타 내 는 Method 대상 의 코드 는 다음 과 같 습 니 다.
      Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});
     Method 류 의 invoke(Object obj,Object args[])방법 으로 받 은 매개 변 수 는 대상 이 어야 하 며,매개 변수 가 기본 형식 데이터 라면 해당 포장 유형의 대상 으로 변환 해 야 합 니 다.invoke()방법의 반환 값 은 항상 대상 입 니 다.실제 호출 된 방법의 반환 유형 이 기본 형식 데이터 라면 invoke()방법 은 해당 포장 유형의 대상 으로 변환 한 다음 되 돌려 줍 니 다.
이 예 에서 InvokeTester 류 의 add()방법의 두 가지 매개 변수 와 반환 값 은 모두 int 형식 임 에 도 불구 하고 add Method 대상 의 invoke()방법 을 호출 할 때 Integer 형식의 매개 변수 만 전달 할 수 있 고 invoke()방법의 반환 유형 도 Integer 유형 이 며 Integer 류 는 int 기본 유형의 포장 류 입 니 다.
Object result=addMethod.invoke(invokeTester,
new Object[]{new Integer(100),new Integer(200)});
System.out.println((Integer)result); //result 는 Integer 형식 입 니 다.

좋은 웹페이지 즐겨찾기