摘要:四后記理解好對象不僅能讓我們更好的認(rèn)識一切皆對象這個(gè)觀點(diǎn),對之后學(xué)習(xí)泛型,類型擦除都是很有幫助的,而對于反射機(jī)制我們只需在適當(dāng)?shù)膱龊侠盟纯伞?/p>
一 前言
很多書上都說,在java的世界里,一切皆對象。其實(shí)從某種意義上說,在java中有兩種對象:實(shí)例對象和Class對象。實(shí)例對象就是我們平常定義的一個(gè)類的實(shí)例:
/** * Created by aristark on 3/28/16. */ public class Person { }
然后利用new關(guān)鍵字:
public class Person { public static void main(String[] args){ Person p = new Person(); } }
而Class對象是沒辦法用new關(guān)鍵字得到的,因?yàn)樗莏vm生成用來保存對應(yīng)類的信息的,換句話說,當(dāng)我們定義好一個(gè)類文件并編譯成.class字節(jié)碼后,編譯器同時(shí)為我們創(chuàng)建了一個(gè)Class對象并將它保存.class文件中。我不知道這樣描述是否妥當(dāng),因?yàn)槲乙惨娺^某些書上直接把.class文件稱之為Class對象。同時(shí)在jvm內(nèi)部有一個(gè)類加載機(jī)制,即在需要的時(shí)候(懶加載)將.class文件和對應(yīng)的Class對象加載到內(nèi)存中??傊羞@樣一個(gè)意識,Person.java文件編譯成Person.class的同時(shí)也會產(chǎn)生一個(gè)對應(yīng)的Class對象。
二 Class對象的獲得上面說了,Class對象是jvm用來保存對象實(shí)例對象的相關(guān)信息的,除此之外,我們完全可以把Class對象看成一般的實(shí)例對象,事實(shí)上所有的Class對象都是類Class的實(shí)例。得到一個(gè)實(shí)例對象對應(yīng)的Class對象有以下三種方式:
1.通過實(shí)例變量的getClass()方法:
Dog dog = new Dog(); Class d = dog.getClass();
2.通過類Class的靜態(tài)方法forName():
try { Class dog1 = Class.forName("Dog"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
3.直接給出對象類文件的.class:
Class dog2 = Dog.class;三 Class對象的使用和反射
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。
簡而言之,我們可以從.class逆向到.java(反編譯),我們可以通過反射機(jī)制來訪問一個(gè)類java對象的屬性,方法,甚至我們可以輕易改變一個(gè)私有成員,看代碼,我們先來定義一個(gè)Cat類:
class Cat{ public static int count; public int age; private String name; static { count = 0; } public Cat(){ age = count++; System.out.println("this is class Cat!"); } public void run(){ } private void ruff(){} }
注意到我們的類中包含靜態(tài)成員,私有變量,靜態(tài)初始化以及私有方法。這里在提一下所謂的懶加載:當(dāng)Cat.java編譯成Cat.class文件后并不會立即被加載到內(nèi)存,而是在它的的靜態(tài)成員第一次被訪問時(shí)才被加載(這么看來,Cat的默認(rèn)構(gòu)造方法也是靜態(tài)的!)
Class c = Cat.class; Field[] fields = c.getDeclaredFields(); for (Field field : fields){ System.out.println(field); }
結(jié)果如下:
public static int Cat.count public int Cat.age private java.lang.String Cat.name
可以看到我們輕而易舉的得到了Cat類的字段信息,再來:
Method[] methods = c.getDeclaredMethods(); for (Method method : methods){ System.out.println(method); }
結(jié)果如下 :
public void Cat.run() private void Cat.ruff()
好玩吧,我們竟然可以在運(yùn)行時(shí)得到類的信息。同時(shí)我們發(fā)現(xiàn)Cat類中的靜態(tài)初始化代碼段并沒有執(zhí)行。接下來我們通過Class對象來獲得對應(yīng)的實(shí)例對象:
try { Cat cat = (Cat) c.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
這時(shí)候靜態(tài)代碼塊執(zhí)行了:
this is class Cat!
接下來我們做一件神奇的事情:
try { Class catClass = Class.forName("Cat"); Field name = catClass.getDeclaredField("name"); name.setAccessible(true); Cat cat2 = (Cat) catClass.newInstance(); name.set(cat2,"Aristark"); System.out.println(cat2.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); }
這次我們使用Class.forname()來獲取Class對象,它的作用是讓jvm查找并加載指定的類,也就是說Cat類的靜態(tài)代碼塊會被執(zhí)行。其次值得注意的是,我們通過Class的幾個(gè)方法訪問了原本不可以被訪問的name屬性:
this is class Cat! Aristark
從這個(gè)意義上來說,反射機(jī)制并不符合OOP的思想,所以我們僅在必要的時(shí)候使用這個(gè)特性就行了。
四 后記理解好Class對象不僅能讓我們更好的認(rèn)識一切皆對象這個(gè)觀點(diǎn),對之后學(xué)習(xí)泛型,類型擦除都是很有幫助的,而對于java反射機(jī)制我們只需在適當(dāng)?shù)膱龊侠盟纯伞#海╆P(guān)于這兩個(gè)知識的深入學(xué)習(xí)稍后我會貼出一些有借鑒意義的文章,大家要關(guān)注哦~
我的微信號是aristark,歡迎交流指正!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65669.html
摘要:反射機(jī)制的應(yīng)用實(shí)例在泛型為的中存放一個(gè)類型的對象。工廠模式可以參考現(xiàn)在我們利用反射機(jī)制實(shí)現(xiàn)工廠模式,可以在不修改工廠類的情況下添加任意多個(gè)子類。 學(xué)習(xí)交流群:669823128java 反射 定義 功能 示例概要:Java反射機(jī)制詳解| |目錄 1反射機(jī)制是什么 2反射機(jī)制能做什么 3反射機(jī)制的相關(guān)API 通過一個(gè)對象獲得完整的包名和類名 實(shí)例化Class類對象 獲取一個(gè)對象的父類與...
近期在維護(hù)公司項(xiàng)目的時(shí)候遇到一個(gè)問題,因?yàn)閷?shí)體類中的 set 方法涉及到了業(yè)務(wù)邏輯,因此在給對象賦值的過程中不能夠使用 set 方法,為了實(shí)現(xiàn)功能,所以采用了反射的機(jī)制給對象屬性賦值,借此機(jī)會也了解了反射的一些具體用法和使用場景,分以下兩點(diǎn)對反射進(jìn)行分析: 反射的優(yōu)勢和劣勢 反射的應(yīng)用場景 反射的優(yōu)勢和劣勢 ??個(gè)人理解,反射機(jī)制實(shí)際上就是上帝模式,如果說方法的調(diào)用是 Java 正確的打開方式...
反射機(jī)制與原理筆記 聲明 文章均為本人技術(shù)筆記,轉(zhuǎn)載請注明出處https://segmentfault.com/u/yzwall 反射機(jī)制 反射:當(dāng)程序無法獲知對象類型時(shí),在運(yùn)行期間動態(tài)獲取類的所有屬性和方法,這種動態(tài)獲取類信息和動態(tài)調(diào)用對象方法的功能稱為反射機(jī)制;反射機(jī)制實(shí)現(xiàn):Class類與java.lang.reflect類庫一起實(shí)現(xiàn)機(jī)制,java.lang.reflect類庫包含F(xiàn)ield...
摘要:反射機(jī)制是什么反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為語言的反射機(jī)制反射機(jī)制能做什么反射機(jī)制主要提供了以下功 反射機(jī)制是什么 反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種...
摘要:的動態(tài)性反射機(jī)制動態(tài)編譯動態(tài)執(zhí)行代碼動態(tài)字節(jié)碼操作動態(tài)語言程序運(yùn)行時(shí)可以改變程序得結(jié)構(gòu)或變量類型典型語言等如下代碼不是動態(tài)語言但有一定的動態(tài)性我們可以利用反射機(jī)制字節(jié)碼操作獲得類似動態(tài)語言的特性的動態(tài)性讓編程的時(shí)候更加靈活反射機(jī)制反射機(jī)制指 1.Java的動態(tài)性 反射機(jī)制 動態(tài)編譯 動態(tài)執(zhí)行JavaScript代碼 動態(tài)字節(jié)碼操作 2.動態(tài)語言 程序運(yùn)行時(shí),可以改變程序得結(jié)構(gòu)或變量...
摘要:一反射機(jī)制概念程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動態(tài)語言,如,是動態(tài)語言顯然,,不是動態(tài)語言,但是有著一個(gè)非常突出的動態(tài)相關(guān)機(jī)制。相關(guān)的為二獲取源頭重點(diǎn)打開權(quán)限所有類的對象其實(shí)都是的實(shí)例。 一、Java反射機(jī)制概念 程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動態(tài)語言,如Python, Ruby是動態(tài)語言;顯然C++,Java,C#不是動態(tài)語言,但是JAVA有...
閱讀 3581·2021-11-18 10:02
閱讀 3143·2019-08-29 18:34
閱讀 3426·2019-08-29 17:00
閱讀 464·2019-08-29 12:35
閱讀 787·2019-08-28 18:22
閱讀 1982·2019-08-26 13:58
閱讀 1709·2019-08-26 10:39
閱讀 2706·2019-08-26 10:11