【狂神說Java】注解和反射

1、反射讓Java變成了半動態(tài)語言

2、反射介紹

反射總體有兩種作用:獲得類的信息、生產(chǎn)動態(tài)代理(AOP、框架有用)
3、反射優(yōu)缺點

4、反射主要API

5、Class類

6、獲得Class對象的方法
(1)getClass() 實例對象 ---> 全類名
假設(shè)CA類的對象a,
則a.getClass()返回CA類對應(yīng)的Class類對象classA,
Class類的toString()被重寫了,a.getClass().toString()返回classA存儲的全類名(CA類的全類名)
(2)Class.forName() 全類名---> Class對象
(3)類名.class
(4)包裝類.TYPE 返回基本類型名,如int

7、Class類的常用方法

8、哪些對象有Class對象

9、從內(nèi)存分析反射過程



生成Class對象,是在加載階段
生成靜態(tài)變量并對其初始化(已經(jīng)知道變量類型了),是在鏈接階段
靜態(tài)代碼的執(zhí)行、類的初始化、創(chuàng)建類的實例,是在初始化階段
10、類的初始化

會引起類初始化的情況有以上五種,對于這5種會觸發(fā)類進行初始化的場景,虛擬機規(guī)范種使用了一個很強烈的限定語:"有且只有",這5種場景中的行為稱為對一個類進行主動引用。除此之外的所有引用類的方式都不會觸發(fā)類的初始化,稱為被動引用。
不會引起類初始化的情況:
(1)子類引用父類的靜態(tài)變量,子類不會初始化,父類會初始化
????(2)定義某個類的數(shù)組,如People[] peoples = new People[10]
(3)引用常量、static final等放入常量池中的數(shù)據(jù)
總之,以上幾種行為都是在鏈接階段就可以完成、不涉及類初始化的行為。
11、類加載器的作用





12、各種類加載器的繼承關(guān)系


13、雙親委派機制
(1)參考 https://www.cnblogs.com/luckforefforts/p/13642685.html

(2)參考中有這么一句話,“如果開發(fā)者嘗試編寫一個與rt.jar類庫中重名的Java類,可以正常編譯,但是永遠無法被加載運行?!?/p>
測試如下:


(3)參考文章中,“從JDK1.2之后,雙親委派模式已經(jīng)被引入到類加載體系中,自定義類加載器時不需要在自己寫雙親委派的邏輯,因此不鼓勵重寫loadClass方法,而推薦重寫findClass方法。”

loadClass()寫著雙親委派機制的過程,不鼓勵重寫oladClass()表明不推薦打破雙親委派機制
按照loadClass()的邏輯,如果自帶的類加載器都無法加載,才可以使用findClass(),即自定義的類加載器。自定義的類加載器也是ClassLoader的子類,所以也算是擴展了雙親委派機制。
如果要可以破壞雙親委派機制,可以重寫loadClass(),見參考文章中的代碼。
(4)雙親委派機制的弊端
參考文章中,“雙親委派模式很好地解決了各個類加載器的基礎(chǔ)類統(tǒng)一問題,越基礎(chǔ)的類由越上層的類加載器進行加載,但是這個基礎(chǔ)類統(tǒng)一有一個不足,當(dāng)基礎(chǔ)類想要調(diào)用回下層的用戶代碼時無法委派子類加載器進行類加載。為了解決這個問題JDK引入了ThreadContext線程上下文,通過線程上下文的setContextClassLoader方法可以設(shè)置線程上下文類加載器?!?/p>
另有百度到的以下解釋,
檢查類是否加載的委派過程是單向的, 這個方式雖然從結(jié)構(gòu)上說比較清晰,
使各個 ClassLoader 的職責(zé)非常明確, 但是同時會帶來一個問題, 即頂層的
ClassLoader 無法訪問底層的 ClassLoader 所加載的類
通常情況下,啟動類加載器中的類為系統(tǒng)核心類,包括一些重要的系統(tǒng)接口,而在應(yīng)用類加載器中,為應(yīng)用類。
按照這種模式,應(yīng)用類訪問系統(tǒng)類自然是沒有問題,但是系統(tǒng)類訪問應(yīng)用類就會出現(xiàn)問題。
比如在系統(tǒng)類中提供了一個接口, 該接口需要在應(yīng)用類中得以實現(xiàn), 該接口還綁定一個工廠方法,用于創(chuàng)建該接口的實例, 而接口和工廠方法都在啟動類加載器中。這時,就會出現(xiàn)該工廠方法無法創(chuàng)建由應(yīng)用類加載器加載的應(yīng)用實例。
14、Class類的常用方法
Field[] getFields()
返回一個包含F(xiàn)ield對象的數(shù)組,存放該類或接口的所有可訪問公共屬性(含繼承的公共屬性)。
Field[] getDeclaredFields()
返回一個包含F(xiàn)ield對象的數(shù)組,存放該類或接口的所有屬性(不含繼承的屬性)。
Field getField(String name)
返回一個指定公共屬性名的Field對象。
Method[] getMethods()
返回一個包含Method對象的數(shù)組,存放該類或接口的所有可訪問公共方法(含繼承的公共方法)。
Method[] getDeclaredMethods()
返回一個包含Method對象的數(shù)組,存放該類或接口的所有方法(不含繼承的方法)。
Constructor[] getConstructors()
返回一個包含Constructor對象的數(shù)組,存放該類的所有公共構(gòu)造方法。
Constructor getConstructor(Class[] args)
返回一個指定參數(shù)列表的Constructor對象。
Class[] getInterfaces()
返回一個包含Class對象的數(shù)組,存放該類或接口實現(xiàn)的接口。
T newInstance()
使用無參構(gòu)造方法創(chuàng)建該類的一個新實例。
String getName()
以String的形式返回該類(類、接口、數(shù)組類、基本類型或void)的完整名。
15、利用反射創(chuàng)建對象


16、利用反射調(diào)用方法修改屬性


利用反射不但可以訪問類的私有屬性、方法、構(gòu)造器,還可以使用私有構(gòu)造器創(chuàng)建對象,重新設(shè)置私有屬性的值,調(diào)用私有方法。

具體代碼參考
https://blog.csdn.net/gao_zhennan/article/details/123828322
https://blog.csdn.net/kaszxc/article/details/109395102
17、利用反射獲取泛型


參考: https://zhuanlan.zhihu.com/p/69132741
18、利用反射獲取注解信息
ORM,使用注解將類與表進行映射
學(xué)到Spring和mybatis的時候再回來看一下