全方位解讀Java反射
反射:reflection
JAVA提供了一種反射機制,反射也稱為反省。
java程序運行以後內存中就是一堆對象,除了對象什麼都沒有。
找對象
拉關係
瞎折騰
對象在運行過程中能否有一種機制查看自身的狀態,屬性和行為。這就是反射機制。
每一個運行中的類,都會有一個class對象,表示這個類的類對象。
獲取class對象的方法:
1.引用名.getClass()
2.類名.getClass()
3.Class.forName()
//方法一 引用.getClass()
People p=new People();
System.out.println(p.getClass().getName()); //包括包名
System.out.println(p.getClass().getSimpleName());//不包括包名
//方法二 類名.getClass()
Class
cla=People.class;
System.out.println(cla.getName());
System.out.println(cla.getSimpleName());
//方法三
try {
Class
claa=(Class
)Class.forName("com.java.reflection.People");
System.out.println(claa.getName());
System.out.println(claa.getSimpleName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Java已經為我們提供了這樣一個類:java.lang.Class,我們無需自己定義Class類,通過Class對象我們可以得到:
類繼承自哪個類
實現了哪些介面
有哪些屬性
有哪些方法
有哪些構造方法
getName(): 獲得類的名稱,包括包名
getSimpleName(): 獲得類的名稱,不包括包名
getSuperClass(): 獲得本類的父類的class對象
getInterfaces():獲得本類所實現的所有介面的class對象
class對象的作用:
public Method[] getDeclaredMethods() throws SecurityException
取得所有當前類聲明的方法,包括public,protected,默認,private四種訪問許可權的方法,但是不包括繼承的方法
public Method[] getMethods() throws SecurityException
取得所有public的方法,包括繼承的,介面中聲明的和自己定義的
獲得所有的公開方法:
Class clazStudent = Student.class;
獲得所以的本類中定義的方法:
Class c = Student.class;
Field[] getDeclaredFields()
取得所有當前類自己定義的屬性,包括四種訪問許可權的
Field[] getFields()
取得所有public的屬性,包括繼承的,介面中聲明的和自己定義的
獲得所以的公開屬性:
Class c = Student.class;
每個Java程序執行前都必須經過編譯、載入、連接、和初始化這幾個階段
載入:查找並載入類的二進位數據
連接:1.驗證:確保被載入的類的正確性
2.準備:為類的靜態變數分配內存,並將其初始化為默認值
3.解析:把類中的符號引用轉換為直接引用
初始化:為類的靜態變數賦予正確的初始值
i、載入是指將編譯後的java類文件(也就是.class文件)中的二進位數據讀入內存,並將其放在
運行時數據區的方法區內,然後再堆區創建一個Java.lang.Class對象,用來封裝類在方法區的數據結構。
即載入後最終得到的是Class對象,並且更加值得注意的是:該Java.lang.Class對象是單實例的,
無論這個類創建了多少個對象,他的Class對象是唯一的!!!!。
而 載入並獲取該Class對象可以通過三種途徑:
Class.forName(類的全路徑)、實例對象.class(屬性)、實例對象getClass()。
在連接和初始化階段,其實靜態變數經過了兩次賦值:
第一次是靜態變數類型的默認值;
第二次是我們真正賦給靜態變數的值。
Java對類的使用分為兩種方式:主動使用和被動使用
主動使用:
1.創建類的實例
2.訪問某個類或介面的靜態變數,或者對該靜態變數賦值
3.調用類的靜態方法
4.反射:Class.forName("com.java.reflection.Person"),即:Class.forName("包名.類名")
5.初始化一個類的子類
6.Java虛擬機啟東市被標明為啟動類的類
而類的初始化時機正是java程序對類的首次主動使用,除了以上6中方式,
其他對類的使用都是被動使用,都不會導致類的初始化。 並且應該注意以下幾個方面:
調用ClassLoader類的loadClass方法載入一個類,並不是對類的主動使用,不會導致類的初始化
當Java虛擬機初始化一個類時,要求它的所有父類都已經被初始化,但是這條規則並不適用於介面。
在初始化一個類時,並不會先初始化它所實現的介面。
在初始化一個介面時,並不會先初始化它的父介面。
因此,一個父介面並不會因為它的子介面或者實現類的初始化而初始化。只有當程序首次使用特定介面的
靜態變數時,才會導致該介面的初始化。
介面的兩重性:可以把介面當做類(因為在介面中有靜態變數時,他可以被初始化);
介面就是介面,和類無關(介面中 沒有構造方法,所以不能被初始化)
從JVM的角度看,我們使用關鍵字new創建一個類的時候,這個類可以沒有被載入。但是
使用Class對象的newInstance()方法的時候,就必須保證:1、這個類已經載入;
2、這個類已經連接了。而完成上面兩個步驟的正是Class的靜態方法forName()所完成的,
這個靜態方法調用了啟動類載入器,即載入 java API的那個載入器。
現在可以看出,Class對象的newInstance()(這種用法和Java中的工廠模式有著異曲同工之妙)
實際上是把new這個方式分解為兩步,即首先調用Class載入方法載入某個類,然後實例化。
這樣分步的好處是顯而易見的。我們可以在調用class的靜態載入方法forName時獲得更好的靈活性,
提供給了一種降耦的手段。
最後用最簡單的描述來區分new關鍵字和newInstance()方法的區別:
newInstance: 弱類型。低效率。只能調用無參構造。
new: 強類型。相對高效。能調用任何public構造。
使用反射的好處:
1.創建的對象不用new
2.可以動態創建對象(把要創建的對象的類型寫在配置文件中,每次程序啟動讀取配置文件,再自動創建對象)
※SpringMVC從入門到精通之第二章
※一篇文章教會你用Java微信語音開發
※程序員的浪漫-java列印心形圖案
※Net毀一 生Java窮三代兩者皆不沾必成高富帥
※Java程序員的職業生涯學習 建議
TAG:java學習吧 |
※抬手之間都是黑科技,vivo X23全方位解讀
※深入解讀Google Lens
※全面解讀Liquidity.Network
※谷歌升級版Transformer官方解讀:更大、更強,解決長文本問題
※mybaits sqlSession 源碼解讀
※disruptor 源碼解讀
※英偉達官方解讀:Volta Tensor Core GPU實現AI性能新里程碑
※從紀錄片中解讀 Martin Margiela 對時尚的顛覆
※專業解讀 Business Analytics項目
※GPU最強對手上線,Jeff Dean十條推文全解讀
※解讀區塊鏈瀏覽器Tokenview.com
※谷歌重拳開放Cloud TPU:GPU最強對手上線,Jeff Dean十條推文全解讀
※Kaggle Carvana 圖像分割比賽冠軍模型 TernausNet 解讀
※解讀目標檢測新範式:Segmentations is All You Need
※《PHP技術大全·第一卷》之static細緻解讀
※深入解讀Service Mesh背後的技術細節
※Rept函數全面解讀
※《Nature Genetics》解讀腫瘤利器,預測癌症進化
※無節操解讀系列之Blockchain
※mybatis的擴展實現源碼解讀