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的反射與代理