為了賬號安全,請及時綁定郵箱和手機立即綁定

全方位解讀Java反射(reflection)

2016.06.01 17:53 9208瀏覽

反射: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<People> cla=People.class;
System.out.println(cla.getName());
System.out.println(cla.getSimpleName());

//方法三
try {
Class<People> claa=(Class<People>)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<Student> clazStudent = Student.class;

Method[] publicMethods = clazStudent.getMethods();
System.out.println("===========所有public方法===========");
for (Method method : publicMethods) {
System.out.println(method.getName());
}

獲得所以的本類中定義的方法:
Class<Student> c = Student.class;

Method[] declaredMethods = c.getDeclaredMethods();
System.out.println("===========所有當前的類自己定義的方法===========");
for (Method m : declaredMethods) {
System.out.println(m.getName());
}

Field[] getDeclaredFields()
取得所有當前類自己定義的屬性,包括四種訪問權限的
Field[] getFields()
取得所有public的屬性,包括繼承的,接口中聲明的和自己定義的

獲得所以的公開屬性:
Class<Student> c = Student.class;

Field[] publicMethods = c.getFields();
System.out.println("============所有public屬性============");
for (Field field : publicMethods) {
System.out.println(field.getName());
}

獲得本類中定義的屬性:
Class<Student> clazStudent = Student.class;
Field[] declaredFields = clazStudent.getDeclaredFields();
System.out.println("==========獲取當前類自己定義的屬性==========");
for (Field field : declaredFields) {
System.out.println(field.getName());
}

java.lang.reflect.Field類
通過Class對象的如下方法可以獲得Field對象
Field getDeclaredField(String name)
Field getField(String name)
Field[] getDeclaredFields()
Field[] getFields()

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

點擊查看更多內容

本文原創發布于慕課網 ,轉載請注明出處,謝謝合作

19人點贊

若覺得本文不錯,就分享一下吧!

評論

相關文章推薦

正在加載中
意見反饋 幫助中心 APP下載
官方微信

舉報

0/150
提交
取消
lpl竞猜