1. 程式人生 > >Java反射機制與動態代理(一)

Java反射機制與動態代理(一)

導讀:
1. 什麼是反射
2. 反射的基本使用
3. 反射的使用例項

一、什麼是反射?

  Java反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。簡而言之,通過反射,我們可以在執行時獲得程式或程式集中每一個型別的成員和成員的資訊。

反射機制是Java語言的一個重要特性,它允許使用者動態獲取類的資訊和動態呼叫物件的方法。它提供的類及對應的功能如下:

  • Class類:代表一個Java類。
  • Field類:代表Java類的屬性。
  • Method類:代表Java類的方法。
  • Constructor類:代表Java類的建構函式。
  • Array類:提供了動態建立陣列,以及訪問陣列元素的靜態方法。
  • Proxy類以及InvocationHandler介面:提供了動態生成代理類以及例項的方法。

注意:反射的核心是JVM在執行時才動態載入類或呼叫方法/訪問屬性,它不需要事先知道執行物件是誰。

二、反射的基本使用

1、獲取Class物件

方法有三種
(1)直接獲取某一個物件的class

Class<?> c = A.class;

(2)使用Class類的forName靜態方法

Class<?> c = Class
.forName("walker.reflect.A");

(3)通過某個物件的getClass()方法獲得

Class<?> c = new A().getClass();
//獲得類的完整名字
System.out.println("類名:" + c.getName());

//獲得類載入器。預設類載入器是sun.misc.Launcher$AppClassLoader
System.out.println("類載入器:" + c.getClassLoader().getClass().getName());
2、反射建立例項

通過反射來建立物件主要有兩種。
(1)使用Class物件的newInstance()方法來建立Class物件對應類的例項

Class<?> c = new A().getClass();
t.newInstance();  //根據預設的構造器建立例項

(2)先通過Class物件獲取指定物件的Constructor物件,在呼叫Constructor物件的newInstance()方法來建立例項。

Class<?> c = new A().getClass();
//獲取A的帶一個String引數構造器
Constructor<?> constructor = c.getConstructor(new Class<?>[]{java.lang.String.class});
//根據指定的構造器建立例項
 Object obj = constructor.newInstance("arg"); 
3、獲取類中宣告的屬性,並通過反射修改宣告的屬性
//獲得當前類和父類中的public型別的所有屬性
Field[] publicField = c.getFields();
// 獲得當前類(不包含父類)宣告的所有屬性,包括private和public
Field[] declareFields = c.getDeclaredFields();
//根據名稱獲取指定屬性
Field specifyField = c.getField("age");
//使用反射修改宣告屬性
specifyField.setAccessible(true);
specifyField.set(newObj, 88);
4、獲取類的方法,並通過反射呼叫物件的方法
//獲得當前類和父類中public型別的所有方法
Method[] publicMethods = c.getMethods();
//獲得當前類(不包含父類)宣告的所有方法,包括public和private
Method[] declareMethods = c.getDeclaredMethods();
//根據方法名和方法引數型別指定獲取一個方法
Method specifyMethod = c.getDeclaredMethod("func1", new Class<?>[]{java.lang.String.class});
//使用反射呼叫物件的方法
specifyMethod.invoke(newObj, "I am reflect method.");
5、獲得繼承的父類和實現的介面
//獲得繼承的父類
Class<?> superclass = c.getSuperclass();
//獲得實現的介面
Class<?>[] interfaces = c.getInterfaces();

三、Java反射使用例項

package walker.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo {
    public static void main(String[] args) throws Exception {
        /*
         * 1-獲得類Class物件
         */
        //(1-1)直接獲取某一個物件的class
        Class<?> class2 = A.class;
        //(1-2)使用Class類的forName靜態方法
        Class<?> demoClass = Class.forName("walker.reflect.A");

        //(1-3)通過某個物件的getClass()方法獲得
        Class<?> class3 = new A().getClass();

        //獲得類的完整名字
        System.out.println("類名:" + demoClass.getName());

        //獲得類載入器。預設類載入器是sun.misc.Launcher$AppClassLoader
        System.out.println("類載入器:" + demoClass.getClassLoader().getClass().getName());


        /*
         * 2-通過反射建立例項
         */
        //(2-1)使用Class物件的newInstance()方法來建立Class物件對應類的例項
        A newObj = (A) demoClass.newInstance();

        //(2-2)先通過Class物件獲取指定物件的Constructor物件,在呼叫Constructor物件的newInstance()方法來建立例項。
        //獲取A的帶一個String引數構造器
        Constructor<?> constructor = demoClass.getConstructor(new Class<?>[]{java.lang.String.class});
        //根據構造器建立例項
        Object obj = constructor.newInstance("walker");


        /*
         * 3-獲得類中宣告的屬性,並通過反射修改宣告的屬性
         */
        //獲得當前類和父類中的public型別的所有屬性
        Field[] publicField = demoClass.getFields();

        // 獲得當前類(不包含父類)宣告的所有屬性,包括private和public
        Field[] declareFields = demoClass.getDeclaredFields();

        //根據名稱獲取指定屬性
        Field specifyField = demoClass.getField("age");

        //使用反射修改宣告屬性
        specifyField.setAccessible(true);
        specifyField.set(newObj, 88);

        /*
         * 4-獲得類的方法,並通過反射呼叫物件的方法
         */
        //獲得當前類和父類中public型別的所有方法
        Method[] publicMethods = demoClass.getMethods();

        //獲得當前類(不包含父類)宣告的所有方法,包括public和private
        Method[] declareMethods = demoClass.getDeclaredMethods();

        //根據方法名和方法引數型別指定獲取一個方法
        Method specifyMethod = demoClass.getDeclaredMethod("func1", new Class<?>[]{java.lang.String.class});

        //使用反射呼叫物件的方法
        specifyMethod.invoke(newObj, "I am reflect method.");

        /*
         * 5-獲得繼承的父類及實現的介面
         */
        //獲得繼承的父類
        Class<?> superclass = demoClass.getSuperclass();

        //獲得實現的介面
        Class<?>[] interfaces = demoClass.getInterfaces();
    }
}
class B {
    public int b;
    public B() {}
}
interface IA {}
class A extends B implements IA {
    public A() {}

    public A(String str){ }

    public A(String str1, String str2) { }

    private String str;
    public int age;

    public int func1(String name) {
        System.out.println("hello " + name);
        return 0;
    }

    public int func1(String name1, String name2) {
        System.out.println("hello " + name1 +"," + name2);
        return 0;
    }
}

【參考資料】