反射
Java反射機制是指在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。
反射是框架的靈魂,它可以有效地降低類之間的耦合,很多框架都運用了反射原理,例如hibernate 的實體類,Spring的AOP等等都有反射的實現。
獲取公共構造器 getConstructors()
獲取所有構造器 getDeclaredConstructors()
獲取該類對象 newInstance()
獲取類名包含包路徑 getName()
獲取類名不包含包路徑 getSimpleName()
獲取類公共類型的所有屬性 getFields()
獲取類的所有屬性 getDeclaredFields()
獲取類公共類型的指定屬性 getField(String name)
獲取類全部類型的指定屬性 getDeclaredField(String name)
獲取類公共類型的方法 getMethods()
獲取類的所有方法 getDeclaredMethods()
獲得類的特定公共類型方法: getMethod(String name, Class[] parameterTypes)
獲取內部類 getDeclaredClasses()
獲取外部類 getDeclaringClass()
獲取修飾符 getModifiers()
獲取所在包 getPackage()
獲取所實現的接口 getInterfaces()
從圖中可以得出以下幾點:
Class 類的實例對象表示正在運行的 Java 應用程序中的類和接口。也就是jvm中有很多的實例,每個類都有唯一的Class對象。
Class 類沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機自動構造的。也就是說我們不需要創建,JVM已經幫我們創建了。
Class 對象用於提供類本身的信息,比如有幾種構造方法, 有多少屬性,有哪些普通方法
1、獲取類對象
獲取類對象有3種方式
Class.forName()(常用)
Hero.class
new Hero().getClass()
在一個JVM中,一種類,只會有一個類對象存在。所以以上三種方式取出來的類對象,都是一樣。(此處準確是在ClassLoader下,只有一個類對象)
三種方式中,常用第一種,第二種需要導入類的包,依賴太強,不導包就拋編譯錯誤。第三種對象都有了還要反射幹什麼。一般都第一種,一個字符串可以傳入也可寫在配置文件中等多種方法。
基本步驟
與傳統的通過new 來獲取對象的方式不同反射機制,反射會先拿到Hero的“類對象”,然後通過類對象獲取“構造器對象”再通過構造器對象創建一個對象,具體步驟:
1.獲取類對象 Class class = Class.forName(“pojo.Hero”);
2.獲取構造器對象 Constructor con = clazz.getConstructor(形參.class);
3 獲取對象 Hero hero =con.newInstance(實參);
2、獲取構造器對象方法
1).批量的方法:
public Constructor[] getConstructors():所有"公有的"構造方法
public Constructor[] getDeclaredConstructors():獲取所有的構造方法(包括私有、受保護、默認、公有)
2).獲取單個的方法:
public Constructor getConstructor(Class… parameterTypes): 獲取單個的"公有的"構造方法
public Constructor getDeclaredConstructor(Class…parameterTypes):獲取"某個構造方法"可以是私有的,或受保護、默認、公有;
3、獲取成員變量並使用
1.獲取HeroPlus類的對象 new方法/第2章中的方法 h
-
獲取屬性 Field f1 = h.getDeclaredField(“屬性名”)
-
修改屬性 f1.set(h,實參),注意這裏的h是對象,不是類對象
補充:
getField和getDeclaredField的區別
getField 只能獲取public的,包括從父類繼承來的字段。
getDeclaredField 可以獲取本類所有的字段,包括private的,但是 不能獲取繼承來的字段。 (注: 這裏只能獲取到private的字段,但並不能訪問該private字段的值,除非加上setAccessible(true))
4、獲取成員方法並使用
獲取HeroPlus類的對象 h
獲取成員方法:
public Method getMethod(String name ,Class<?>… parameterTypes):獲取"公有方法";(包含了父類的方法也包含Object類)
public Method getDeclaredMethods(String name ,Class<?>… parameterTypes) :獲取成員方法,包括私有的(不包括繼承的)
參數解釋:
name : 方法名;
Class … : 形參的Class類型對象
調用方法
Method --> public Object invoke(Object obj,Object… args):
參數說明:
obj : 要調用方法的對象;
args:調用方式時所傳遞的實參; 反射一般使用在框架中,框架需要很強的靈活性