Programming > Java

[java] reflection 리플렉션

 

리플렉션에 사용할 샘플 클래스 (생성자, static, non static, getter/setter 메소드를 갖는다.)

package com.emunhi.리플렉션.lib;

public class MyClass {

    public int no;
   
    String name;
   
    static String ST_NAME = "static Name";

   // default 생성자
    public MyClass() {
        super();
    }
   // 인자를 갖는 생성자
    public MyClass(int no, String name) {
        this.no = no;
        this.name = name;
    }
    public static String getStatic(String str) {  // static 메소드
        return ST_NAME + str;
    }
    public String show(String str) {  // 메소드
        System.out.printf("%03d : %20s : %s\n", no, name, str);
        return str + name;
    }
    --- getter, setter ---
    ... ...

}

 

[ 1 ] 클래스 객체를 얻는 방법 [ 3가지 패턴 ]

        /** ① Instance 로 부터 클래스 취득 **/
        MyClass obj = new MyClass(10, "Tom");
        Class<? extends MyClass> cls1 = obj.getClass();
       
        /** ② 클래스명으로 부터 생성 **/
        Class<MyClass> cls2 = MyClass.class;
       
        /** ③ 패키지명으로 부터 생성(FQCN:Fully Qualified Class Name) **/
        Class<?> cls3 = Class.forName("com.emunhi.리플렉션.lib.MyClass");

[ 2 ] 생성자 얻기 (Constructor)

        Constructor<? extends MyClass> cons1 = cls1.getDeclaredConstructor(int.class, String.class);
        Constructor<MyClass> cons2 = cls2.getDeclaredConstructor(int.class, String.class);
        Constructor<?> cons3 = cls3.getDeclaredConstructor(int.class, String.class);

[ 3 ] 클래스 인스턴스 얻기

        // ① 생성자를 통해서 인스턴스 얻기
        MyClass inst1 = (MyClass)cons1.newInstance(22, "aaaaa");
        inst1.show("aaa");
       
        MyClass inst2 = (MyClass)cons2.newInstance(33, "bbbbb");
        inst2.show("bbb");
       
        MyClass inst3 = (MyClass)cons3.newInstance(44, "ccccc");
        inst3.show("ccc");
       
        // ② 클래스에서 바로 인스턴스 얻기
        //Object objIns = cls1.getDeclaredConstructor().newInstance();
        MyClass objIns1 = cls1.getDeclaredConstructor().newInstance();
        MyClass objIns2 = cls1.getDeclaredConstructor(int.class, String.class).newInstance(987, "MinSu");
        objIns1.show("ddd");
        objIns2.show("eee");

[ 4 ] 모든 생성자를 취득하기

        // getDeclaredConstructors()->getConstructors() 변경시 public 생성자만 취득
        Constructor<?> conArr[] = cls1.getDeclaredConstructors();
        for(Constructor<?> cs: conArr) {
            System.out.println(cs);
        }

[ 5 ] 메소드 찾고 실행하기

        // getDeclaredMethods()->getMethods() 변경시 상위 Object까지 상속 메소드를 모두 취득한다.
        Method mdArr[] = cls1.getDeclaredMethods();
        for(Method md: mdArr) {
            System.out.println(md);
        }
       
        // 메소드 실행
        Method md1 = cls1.getDeclaredMethod("setNo", int.class);
        md1.invoke(inst1, 500);
        inst1.show("aaa");
       
        // 메소드 특성확인
        System.out.println("method property : " + md1.getDeclaringClass());
        System.out.println("method property : " + md1.getName());
        System.out.println("method property : " + md1.getReturnType());
       
        Method md2 = cls1.getMethod("getNo");
       
        // 메소드를 실행하기
        System.out.println();
        System.out.println("invoke exec : " + md2.invoke(inst1));
        System.out.println("invoke exec : " + md2.invoke(objIns1));
        System.out.println("invoke exec : " + md2.invoke(objIns2));

[ 6 ] 필드에 접근하기

        // getDeclaredFields()-> getFields()로 변경시 public 필드만 취득한다.
        Field fldArr[] = cls1.getDeclaredFields();
        for(Field fld: fldArr) {
            System.out.println(fld);
        }
       
        Field fldName1 = cls1.getDeclaredField("name");
        System.out.println(fldName1);
        fldName1.setAccessible(true);    // private변수에 접근하기 위해서...
        fldName1.set(inst1, "개구리");
        inst1.show("FIELD");
       
        System.out.println("\n====[ Static ]====");
       
        Method mdStatic = cls1.getDeclaredMethod("getStatic", String.class);
        System.out.println(mdStatic.invoke(null, " : GET"));    // 인스턴스를 null 로 전달
       
        Field fldStatic = cls1.getDeclaredField("ST_NAME");
        fldStatic.setAccessible(true);    // private변수에 접근하기 위해서...
        System.out.println(fldStatic.get(null));    // 인스턴스를 null 로 전달

 

전체 샘플 보기

package com.emunhi.리플렉션;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.emunhi.리플렉션.lib.MyClass;

public class A01_생성하기 {

    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
       
        System.out.println("\n====[ Class ]====");
        /**
         * [ 1 ] 클래스 객체를 얻는방법 (3가지)
         */

        /** ① Instance 로 부터 클래스 취득 **/
        MyClass obj = new MyClass(10, "Tom");
        Class<? extends MyClass> cls1 = obj.getClass();
       
        /** ② 클래스명으로 부터 생성 **/
        Class<MyClass> cls2 = MyClass.class;
       
        /** ③ 패키지명으로 부터 생성(FQCN:Fully Qualified Class Name) **/
        Class<?> cls3 = Class.forName("com.emunhi.리플렉션.lib.MyClass");
       
        /**
         * [ 2 ] 생성자 얻기 (Constructor)
         */
        Constructor<? extends MyClass> cons1 = cls1.getDeclaredConstructor(int.class, String.class);
        Constructor<MyClass> cons2 = cls2.getDeclaredConstructor(int.class, String.class);
        Constructor<?> cons3 = cls3.getDeclaredConstructor(int.class, String.class);
       
        /**
         * [ 3 ] 클래스 인스턴스 얻기
         */
        // ① 생성자를 통해서 인스턴스 얻기
        MyClass inst1 = (MyClass)cons1.newInstance(22, "aaaaa");
        inst1.show("aaa");
       
        MyClass inst2 = (MyClass)cons2.newInstance(33, "bbbbb");
        inst2.show("bbb");
       
        MyClass inst3 = (MyClass)cons3.newInstance(44, "ccccc");
        inst3.show("ccc");
       
        // ② 클래스에서 바로 인스턴스 얻기
        //Object objIns = cls1.getDeclaredConstructor().newInstance();
        MyClass objIns1 = cls1.getDeclaredConstructor().newInstance();
        MyClass objIns2 = cls1.getDeclaredConstructor(int.class, String.class).newInstance(987, "MinSu");
        objIns1.show("ddd");
        objIns2.show("eee");

       
        System.out.println();
       
        // 모든 생성자를 취득한다.
        // getDeclaredConstructors()->getConstructors() 변경시 public 생성자만 취득
        Constructor<?> conArr[] = cls1.getDeclaredConstructors();
        for(Constructor<?> cs: conArr) {
            System.out.println(cs);
        }
       
        System.out.println("\n====[ Method ]====");
        /**
         * [ 4 ] 메소드(Method) 찾기
         */
        // getDeclaredMethods()->getMethods() 변경시 상위 Object까지 상속 메소드를 모두 취득한다.
        Method mdArr[] = cls1.getDeclaredMethods();
        for(Method md: mdArr) {
            System.out.println(md);
        }
       
        // 메소드 실행
        Method md1 = cls1.getDeclaredMethod("setNo", int.class);
        md1.invoke(inst1, 500);
        inst1.show("aaa");
       
        // 메소드 특성확인
        System.out.println("method property : " + md1.getDeclaringClass());
        System.out.println("method property : " + md1.getName());
        System.out.println("method property : " + md1.getReturnType());
       
        Method md2 = cls1.getMethod("getNo");
       
        // 메소드를 실행하기
        System.out.println();
        System.out.println("invoke exec : " + md2.invoke(inst1));
        System.out.println("invoke exec : " + md2.invoke(objIns1));
        System.out.println("invoke exec : " + md2.invoke(objIns2));
       

        System.out.println("\n====[ Field ]====");
        /**
         * [ 5 ] 필드 찾기
         */
        // getDeclaredFields()-> getFields()로 변경시 public 필드만 취득한다.
        Field fldArr[] = cls1.getDeclaredFields();
        for(Field fld: fldArr) {
            System.out.println(fld);
        }
       
        Field fldName1 = cls1.getDeclaredField("name");
        System.out.println(fldName1);
        fldName1.setAccessible(true);    // private변수에 접근하기 위해서...
        fldName1.set(inst1, "개구리");
        inst1.show("FIELD");
       
        System.out.println("\n====[ Static ]====");
       
        Method mdStatic = cls1.getDeclaredMethod("getStatic", String.class);
        System.out.println(mdStatic.invoke(null, " : GET"));    // 인스턴스를 null 로 전달
       
        Field fldStatic = cls1.getDeclaredField("ST_NAME");
        fldStatic.setAccessible(true);    // private변수에 접근하기 위해서...
        System.out.println(fldStatic.get(null));    // 인스턴스를 null 로 전달

    }
}