淺析java.lang.Class

最近溫習(xí)了一下java的反射機(jī)制,發(fā)現(xiàn)之前學(xué)習(xí)反射的時(shí)候沒(méi)有留下只言片語(yǔ),補(bǔ)上補(bǔ)上?。?!

反射的概念:

比如我們想看看我們自己長(zhǎng)什么樣子,我們自己肯定看不到自己長(zhǎng)什么樣子,所以,我們借助鏡子,通過(guò)鏡子的反射看到我們的樣子,可以看清我們自己的五官;

同理,在Java中運(yùn)行的類,也有這么一面鏡子,可以反射該類的一些行為和屬性,而這個(gè)反射就體現(xiàn)在java.lang.Class中;

通過(guò)Class對(duì)象,可以得到某個(gè)類的一些行為和屬性,甚至我們通過(guò)反射可以操作這個(gè)對(duì)象的行為和屬性;這就是反射機(jī)制;

要想理解反射,我們先來(lái)了解一下java.lang.Class這個(gè)‘萬(wàn)能’的類;

獲取Class實(shí)例的幾種方式:

(1)通過(guò)全類名獲取Class實(shí)例,這也是最常用的一種方式

public void testClassForName(){

? ??String className = "com.test.bean.Preson";

? ??Class clazz = Class.forName(className);

}

為什么說(shuō)這是一種最常用的一種方式,相信大家都用過(guò)Spring或者M(jìn)yBatis等等這類框架,在使用這類框架的時(shí)候,免不了與該框架的XML配置文件打交道,在很多配置的地方都會(huì)填寫(xiě)一個(gè)全類名;

看過(guò)源碼的同學(xué)應(yīng)該就知道,因?yàn)檫@些框架會(huì)先解析XML配置文件的到這個(gè)全類名,通過(guò)這個(gè)全類名來(lái)得到Class對(duì)象,完成后面的反射調(diào)用的動(dòng)作;

(2)通過(guò)getClass的方式得到Class實(shí)例

public void testGetClass(Object obj){

? ??Class clazz = obj.getClass();

}

這里為什么用Object作為入?yún)⒛??因?yàn)楦鄷r(shí)候我們不知道外面?zhèn)鬟M(jìn)來(lái)的是什么對(duì)象,使用Object接受就可以接受任何java對(duì)象,那么通過(guò)反射就可以獲得到相應(yīng)的Class

(3)通過(guò)類.class的形式獲取

public void testClass(){

? ??Class clazz = Person.class;

}

(4)通過(guò)類加載器的形式獲取

public void testClassLoader(){

? ? ClassLoader classLoader = this.getClass().getClassLoader();

? ? Class clazz = classLoader.loadClass(className);

}

也就是說(shuō),我們得到Class對(duì)象,就可以為所欲為了,可以利用反射機(jī)制來(lái)調(diào)用該類的方法或者屬性;

說(shuō)完Class,我們說(shuō)下幾個(gè)常用的相關(guān)類;這幾個(gè)類的使用方式都差不多;


java.lang.reflect.Constructor

這個(gè)類是專門描述某個(gè)類的構(gòu)造方法,可以通過(guò)Class對(duì)象獲得到類中定義的構(gòu)造方法;

//獲取構(gòu)造器

public void testConstructor() throws Exception{

????String className = "com.test.bean.Person";

????Class clazz = Class.forName(className);

????//通過(guò)Class對(duì)象獲取Constructor對(duì)象

????Constructor constructor = clazz.getConstructor();

????System.out.println(constructor.getName());

}

parameterTypes:表示構(gòu)造器的參數(shù)列表,如果想獲取無(wú)參構(gòu)造器,這個(gè)參數(shù)不要傳了;

但是這個(gè)clazz.getConstructor();只能獲取到構(gòu)造器為public類型的,不能獲取到private修飾的構(gòu)造器;

//獲取私有構(gòu)造器

public void testConstructor() throws Exception{

????String className = "com.test.bean.Person";

????Class clazz = Class.forName(className);

????//通過(guò)Class對(duì)象獲取private 修飾的Constructor對(duì)象

????Constructor constructor = clazz.getDeclaredConstructor();

????System.out.println(constructor.getName());

}

同時(shí),如果想調(diào)用私有的構(gòu)造器,調(diào)用前要調(diào)用一下setAccessible(true),獲取調(diào)用私有方法的權(quán)限,否則會(huì)報(bào)異常

//獲取私有構(gòu)造器,并執(zhí)行私有構(gòu)造器

public void testConstructor() throws Exception{

????String className = "com.test.bean.Person";

????Class clazz = Class.forName(className);

????//通過(guò)Class對(duì)象獲取private 修飾的Constructor對(duì)象

????Constructor constructor = clazz.getDeclaredConstructor();

????constructor.setAccessible(true);

????//調(diào)用構(gòu)造器創(chuàng)建實(shí)例

????Object obj = constructor.newInstance();

????System.out.println(constructor.getName());

}

通過(guò)上面,就會(huì)發(fā)現(xiàn),Java的三大特性:封裝、繼承、多態(tài),這里面的封裝對(duì)反射來(lái)說(shuō)是無(wú)用了,通過(guò)反射可以破壞他的封裝;啊哈哈哈。。。

java.lang.reflect.Method

這個(gè)類描述了類中的方法,通過(guò)這個(gè)Method對(duì)象,可以操作類中定義的方法;

//通過(guò)反射獲得類定義的Mehtod,但是獲取不到private修飾的方法

Mehtod method = clazz.getMethod('setName', String.class);

//獲取本類中定義的方法,包括私有方法也可以獲取

Method method = clazz.getDeclaredMethod("test",String.class);

獲取指定的Method的時(shí)候需要傳入兩個(gè)參數(shù):

1.方法名

2.方法的參數(shù)列表類型,比如方法的入?yún)⑹荢tring類型的,那么這里就是String.class

//獲取本類和父類中public的所有方法集合,但是獲取不到私有方法

Method[] methods = clazz.getMethods();

//獲取本類所有方法集合,包括私有方法

Method[] methods = clazz.getDeclaredMethods();

同樣,在調(diào)用private修飾的方法之前,要調(diào)用setAccessible(true);

//通過(guò)method調(diào)用方法,這個(gè)才是重點(diǎn)

public Object invoke(Object obj,Object... args);

obj:調(diào)用哪個(gè)對(duì)象中的方法

args:方法的參數(shù)

method.invoke(clazz.newInstance(), "helloWorld");

java.lang.reflect.Field:屬性

public void testField() throws Exception{

????String className = "com.test.classloader.bean.Person";

????Class clazz = Class.forName(className);

????//先通過(guò)反射獲得到實(shí)例

????Object obj = clazz.newInstance();

????//獲取對(duì)象中指定的屬性

????Field field = clazz.getField("name");

????//為屬性賦值

????field.set(obj, "hello");

????System.out.println(obj);


? ??//獲取private 修飾的成員屬性

????Field field1 = clazz.getDeclaredField("name");

????field1.setAccessible(true);

????field1.set(obj, "world");

????System.out.println(obj);

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容