目錄
1 反射機制
2 反射的應用:動態代理?
3?注解
1 反射機制
????????反射機制(Reflect Machanism),是指在程序運行期間借助Reflect API獲取任何類的內部信息,并能直接操作對象的內部屬性以及方法,Java本身而言是靜態語言但是由于Java反射機制的存在又被人們視為是動態語言。動態語言就是一類在運行時可以改變其結構的語言,反之而言的就是靜態語言概念。
????????類被加載完成之后,在堆內存的方法區中就產生了一個Class類型的對象,這個對象就包含了完整的類的結構信息,我們可以通過這個對象看到類的結構。這個對象就像是一面鏡子,透過這個鏡子看到類的結構,所以這個過程被形象的稱為是反射。
????????Java提供了一個類java.lang.Class,通過類名.class獲取這個類編譯之后的class文件對象,再通過這個class對象解析得到這個類的所有成分包括:構造器對象(Constructor)、成員變量對象(Field)、成員方法對象(Method)。
反射技術第一步:獲取Class類對象
一?:?類名.class 二?:?對象.getClass() 三?:?Class.forName("類的全限名")
?獲取class對象的名稱
反射技術第二步:獲取類成分
獲取構造器對象:
?? 在按照參數匹配構造器的時候,參數的先后順序唯一固定一個構造器,一般都是使用帶有declared的方法,不加declared的方法功能太差只能獲取public方法。?
通過構造器對象創建對象:
?? 如果構造器被私有化了的話,也就是說構造器被private修飾了,需要使用構造器對象名.setAccessible(true)暴力打開私有構造器的權限
獲取變量對象:
獲取
使用變量對象取值賦值?
獲取方法對象:
獲取方法對象:
?使用方法對象執行方法:
總結
第一步,獲取class類對象
第二步,獲取構造器對象去new一個對象?
第三步,通過對象可以設置對象的變量值或者調用對象中的方法
獲取成員變量并取值賦值?
調用方法
??
?? 反射不僅可以破壞面向對象的封裝性(暴力反射),還可以破壞泛型的約束性,具體原因是泛型是在編譯階段的約束,在編譯完成運行時會被擦除泛型約束此時就可以無視泛型約束了,而反射就是在運行時改變操作對象結構的一種機制,于是可以使用反射來破壞泛型的約束性。
反射綜合案例
2 反射的應用:動態代理?
什么叫做代理設計模式?
? ? ? ? 代理就是使用一個代理將對象包裝起來,然后使用該代理對象取代原始對象,任何對于原對象的調用都要經過代理實現,代理對象決定了是否以及何時將方法調用轉到原始對象上去。其中代理模式包括兩種:靜態代理、動態代理。
靜態代理:
? ? ? ? 靜態代理就是代理類和目標對象的類都是在編譯期間就確定下來的,不利于程序的擴展,同時每一個代理類都只能為一個接口所服務,這樣一來程序的開發中必然會產生過多的代理。
第一步:定一個共用接口
?第二步:定義一個被代理類實現共用接口
第二步:定義一個代理類實現共用接口?
第四步:創建代理類對象并調用他的方法,在代理類方法定義的時候會被引用代理對象調用被代理類方法,具體何時引用被代理對象要取決于代理類的方法何時引用,所以說代理對象決定了是否以及何時將方法調用轉到原始對象上去
動態代理:
? ? ? ? 動態代理指的是客戶通過代理類來調用其他對象的方法,并且是在程序運行時根據需要動態創建目標類的代理對象。相較于靜態代理,動態代理將抽象角色(接口)中聲明的所有方法都轉移到處理器的一個集中方法中進行處理,這樣一來我們就可以更加靈活和統一的處理中多方法。
第一步:創建一個共用接口
第二步:定義一個被代理類實現共用接口?
第三步:定義一個代理工廠類用于實現創造代理類的功能,代理工廠類不直接實現共用接口,而是利用反射實現與被代理類一樣的接口,代理類調用被代理類的同名方法要通過handler對象實現,handler對象則是實現了InvocationHandler接口的類創建(new)出來的,這個類底層重寫了invoke方法使用反射去調用被代理類的同名方法
代理工廠
?實現了InvocationHandler接口的類
第四步:創建代理類對象并調用他的方法,進而調用被代理類的方法
??
?? 這個代理工廠不只可以代理被代理類siChuanPeople類,還可以代理上個靜態代理案例中的被代理類HxekClothFactory類,因為使用了反射,所以代理工廠可以動態的創建所需要的代理類,而不需要用一個創一個
??? 動態代理只需要理解第三步的具體步驟即可,其他三步與靜態代理的寫法一樣。
3?注解
? ? ? ? 注解(Annotation)實際上就是代碼里的一些特殊標記,這些標記可以在編譯、類加載、類運行的時候被讀取,并執行相應的處理。注解可以想修飾符一樣使用,用于修飾包、類、構造器、方法、成員變量、參數、局部變量的聲明,這些信息被保存在Annation的鍵值對"name=value"中。
? ? ? ? Java SE階段使用的注解比較少,主要是未來框架的學習注解會被頻繁的使用,框架=注解+反射+設計模式。
JDK中內置的三個基本注解:
@Override
????????@Override注解就是在繼承父類時可能會需要重寫父類中的方法,還有就是實現一個接口必須重寫接口中的抽象方法。只要是重寫方法的時候就可以使用@Override注解,@Override注解的作用是:對重寫的方法規范化,一般來說重寫方法需要做到方法的聲明和參數列表相同方法體可以不同,凡是重寫方法時沒有遵守規范@Override注解就會報紅,說明重寫方法失敗
?@Deprecated?
?????????@Deprecated????注解表示其所修飾的元素(類、方法……)已經過時,雖然不影響該元素的繼續使用,但是建議最好還是不使用。
過時比較多的當屬Date類,以下注解就表明下面的構造器已經過時,不推薦使用
@SuppressWarnings
????????@SuppressWarnings注解用于抑制編譯器警告,比如說定義一個變量但是并沒有在下文中對這個變量進行引用,這是就會在編譯器也就是IDEA右邊報一個警告,警告不會影響代碼的運行。
加上@SuppressWarnings注解之后這個警告就會消失,哪怕這個變量依然沒有在下面進行引用,此時編譯器右邊沒有了黃色警告
? ? ? ? 元注解就是用于注解(修飾)其他注解的注解
JDK中內置的四個元注解:
@Retention
????????@Retention注解用于指定被修飾注解的生命周期。注解中包含了一個RetentionPolicy類型(枚舉類)的成員變量,有以下三種取值
- RetentionPolicy.SOURCE:在源文件中有效,編譯階段丟棄不會在編譯之后的.class文件中存在的
- RetentionPolicy.CLASS:在class文件中有效,保存在編譯之后的.class文件中不會在運行時進行加載。注解上不聲明@Retention的話默認就是取這個值
- RetentionPolicy.RUNTIME:在運行時依然有效,也就是說可以使用反射進行成分的獲取……
@Target
????????@Target注解用于指定被修飾的注解能用于修飾哪些程序元素。注解中也定義了一個枚舉類,里面包含以下值
- TYPE:類、接口(包括注釋類型)或枚舉聲明,
- FIELD:字段聲明(包括枚舉常量)
- METHOD:方法聲明
- PARAMETER:正式的參數聲明
- CONSTRUCTOR:構造函數聲明
- LOCAL_VARIABLE:局部變量聲明,
- ANNOTATION_TYPE:注釋類型聲明
- PACKAGE:包聲明
- TYPE_PARAMETER:類型參數聲明
- TYPE_USE:類型的使用
@Documented
????????@Documented注解指定被修飾的注解將會在編譯時被javadoc工具提取成為文檔。也就是說經過javadoc編譯之后的class文件中依然會保留這個注解,正常情況下經過編譯之后的.class文件不會保留注解。
@Inherited
????????@Inherited注解指定被修飾的注解將具有繼承性。也就是說,當一個注解加上?@Inherited修飾之后,被這個注解修飾的類的子類也同時被這個注解所修飾了(繼承性)。