天天看點

Java反射機制(一):認識Class類

一、 認識class類

1.1 正常我們再使用一個類時,大多情況是先擷取類的對象,然後通過對象去操作類中的屬性或方法。 那,大家有沒有想過,如果我們已經有了一個類的對象,我能否通過該對象去擷取到類的資訊呢?答案是肯定的。

java允許通過對象來找到其所在類的資訊,那麼實際上就是class類的功能。

接下來,我們先看一個例子,定義一個類person,并執行個體化person類的一個對象,我們通過該對象去尋找到該person類

輸出: com.chen.yuan.ref.person

我們發現,現在所有的操作都和我們以前的習慣是反着的了,即通過對象去擷取類,而非通過類擷取對象。

1.2 從上面的例子中我們可以看出,對象可以通過getclass()方法,擷取對象的源頭(類),那這個getclass()方法在哪裡定義的呢? 檢視jdk可以看到,在object中定義了這個方法,此方法将被所有子類繼承:

· public final class getclass()

` 以上方法的傳回值的類型是一個class類,實際上此類是java反射的源頭。 所謂的反射從程式的運作結果可以這樣了解: 可以通過對象反射求出類的名稱。

1.3 class類中常用的方法:

forname(string classname)

傳入完成的”包.類”名稱執行個體化class對象

getname()

獲得類的完整名字

getfields()

獲得類的public類型的屬性

getdeclaredfields()

獲得類的所有屬性

getmethods()

獲得類的public類型的方法

getdeclaredmethods()

獲得類的所有方法

getmethod(string  name,  class[]  parametertypes)

擷取類的特定方法(name參數指定方法名字,parametertypes參數指定方法參數類型)

getconstructors()

獲得類的public類型的構造方法

getconstructor(class[] parametertypes) 

獲得類的特定構造方法(parametertypes參數指定構造方法的參數類型)

newinstance()

 通過類的不帶參數的構造方法建立這個類的一個對象

1.4 執行個體化class的三種方法:

通過檢視源碼或jdk文檔我們可以發現,class類的構造方法是私有的,即它無法通過構造方法進行執行個體化。 java提供了三種可以執行個體化class對象的方法:

a) 使用class類的靜态方法forname:       

class.forname("java.lang.string");

b) 使用類的.class文法: 

string.class;

c) 使用對象的getclass()方法(java.lang.object類中的方法): 

string s = "aa"; 

class<?> clazz = s.getclass();

二、 使用class類

上文已經提到了一些class類中的常用方法,當然不全,可以檢視jdk文檔,了解更加詳細的class中的方法。

接下來,我們假設,如果現在已經執行個體化好了class對象,則就可以通過class類中提供的newinstance()方法,執行個體化源類(比如person)的對象。

輸出: person [name=無緣, age=25]

通過以上代碼,我們發現,即使不使用new關鍵字,對象也可以進行執行個體化操作,這就是反射的作用。

但是,我們需要記住,此時的操作,必須為person類一共一個無參數的構造方法,否則無法執行個體化。

運作之後,程式會報錯:

exception in thread "main" java.lang.instantiationexception: com.chen.yuan.ref.person

at java.lang.class.newinstance(class.java:359)

at com.chen.yuan.ref.classdemo.main(classdemo.java:42)

是以說,使用以上的方式,實際上還是需要類中構造方法的支援,才能進行對象的執行個體化。

如果想要解決該問題,則必須明确指定要調用的構造方法,并傳遞參數。但是,在實際開發中,一般用到反射的地方我們都要求類中含有一個無參的構造方法,便于操作。

如果想調用有參數的構造方法進行反射執行個體化,可以按如下步驟:

1) 通過class類的getconstructors()取得本類中的全部構造方法。

2) 向構造方法中傳遞一個對象數組進去,裡面包含了構造方法中所需的各個參數。

3) 之後通過constructor執行個體化對象。

可以看出,通過這種方式,我們确實可以做到對象的執行個體化,但是,我們最好不要如此操作,最好能為類添加一個無參的構造方法。