當前位置:
首頁 > 知識 > 全方位解讀Java反射

全方位解讀Java反射

全方位解讀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.可以動態創建對象(把要創建的對象的類型寫在配置文件中,每次程序啟動讀取配置文件,再自動創建對象)


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 java學習吧 的精彩文章:

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的擴展實現源碼解讀