1. 程式人生 > >Java的反射與代理

Java的反射與代理

使用 靜態代理 jvm 初始 識別 動態加載 目標 java反射機制 type

java的類型信息在運行時如何表示?

通過Class對象,class類是程序運行期間,為所有的對象維護一個運行時的類型標識,保存這些信息的類被稱為class。

如何獲取類的class對象引用?

1. Class.forName();forname是class類的靜態方法。

2. 如果已經有一個對象,可以調用對象的getClass(),此方法屬於根類object。

3. 使用類字面常量.class;不僅可以用於普通的類,還可以用於接口,數組,以及基本數據類型。

註意,一個class對象表示一個類型,未必一定是一種類。如Class c = int.class,c不是類,但是一個class類型對象。

.class和forName()的區別:

程序中每一個類都有一個class對象,所有的類都是在對其第一次使用時,動態加載到JVM中。當程序創建第一個對類的靜態成員的引用時(構造器也是類的靜態方法),就會加載這個類,然後進行類的靜態初始化。通過.class得到class對象引用,不會觸發類的初始化,而使用forName()會使類進行初始化。

Class類是泛型的。我們可以用泛型語法,讓編譯器進行額外的類型檢查。

如 Class<?> intClass = int.class; Class<House> houseType = House.class;

我們可以根據得到的class引用,判斷一個對象obj是不是某個Class類型的實例(如類名為Base)。

1. obj instanceof Base

2. Base.class.isInstance(obj)

instanceof 和insInstance都保持了類型的概念,即可以識別出繼承的關系。

若我們想要在運行時獲取類的信息呢?在編譯時不能確定需要的是哪個類,所以.class和getClass()是顯然不好用的。

Java反射機制主要提供了以下功能: 在運行時判斷任意一個對象所屬的類;在運行時構造任意一個類的對象;在運行時判斷任意一個類所具有的成員變量和方法;在運行時調用任意一個對象的方法;生成動態代理。

Class類與java.lang.reflect類庫一起對反射的概念進行了支持。

在Class類中:

Static Class forName(String className)可以得到該類型的對象引用

Object newInstance()創建該類型實例

默認使用類的無參數構造器,如果創建有參數實例,需要先調用getConstructors(),得到一個Constructor構造器的實例。

Eg.e.getClass().newInstance() e.getConstructor(String.class).newInstance(“233”)

Field[] getFields()

Method[] getMethods()

Constructor[] getConstructors()

java.lang.reflect類庫中有三個類:
Field:描述類的域

Method:描述類的方法

Constructor:描述類的構造器

在method類中:

Public Object invoke(Object implicitPara,Object[] explicitPara) 調用任意方法。

通過這些類庫中類的方法可以實現動態獲取類型信息。


代理是基本的設計模式之一,代理通常充當著中間人的身份。一個對象不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

靜態代理:寫在代碼裏,通過中間類去操作實際類,也就是被代理的類

動態代理:動態地創建代理,動態地實現對實際類的調用。

反射和java.lang.reflect.Proxy等相關類實現了動態代理。

動態代理分為3個步驟:

1. 建立委托類,即被代理的類,創建Interface接口和實現類;

2. 創建實現了InvocationHandler接口的代理類,在invoke()內執行代理操作;

3. 創建代理對象,將代理對象傳遞給調用者。

通過調用proxy的靜態方法newProxyInstance()創建動態代理,

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

這個方法需要三個參數:

1. ClassLoader loader指明生成代理對象使用的類裝載器

2. Class<?>[] interfaces指定代理器實現的接口列表

3. InvocationHandler h指明Invocation接口的一個實現,就是定義的代理類要做的事情。

通過動態代理,不管調用代理對象的什麽方法,都是調用代理器的invoke方法,在這裏人為地決定了如何調用被代理對象的原始方法,如何進行額外的處理。相當於對被代理對象直接方法調用的攔截。


Java的反射與代理