標籤:動態擷取 注意 運行 靜態 ceo 實現 設計 好用 目標
java的類型資訊在運行時如何表示?
通過Class對象,class類是程式運行期間,為所有的對象維護一個運行時的類型標識,儲存這些資訊的類被稱為class。
如何擷取類的class對象引用?
1. Class.forName();forname是class類的靜態方法。
2. 如果已經有一個對象,可以調用對象的getClass(),此方法屬於根類object。
3. 使用類字面常量.class;不僅可以用於普通的類,還可以用於介面,數組,以及基礎資料型別 (Elementary Data Type)。
注意,一個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的反射與代理