日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

详解Java反射机制

發(fā)布時間:2024/4/14 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解Java反射机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、什么是JAVA的反射機制

Java反射是Java被視為動態(tài)(或準動態(tài))語言的一個關鍵性質。這個機制允許程序在運行時透過Reflection APIs取得任何一個已知名稱的類的內部信息,包括其方法(諸如public, static 等)、父類(例如Object)、實現接口(例如Cloneable),也包括屬性和方法的所有信息,并可于運行時改變屬性值或調用方法。

Java反射機制容許程序在運行時加載、探知、使用編譯期間完全未知的類。Java可以加載一個運行時才得知名稱的類,獲得其完整結構。

簡言之,JAVA反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法;這種動態(tài)獲取的信息以及動態(tài)調用對象的方法的功能稱為java語言的反射機制。

二、JDK中提供的Reflection API

Java反射相關的API在包java.lang.reflect中,JDK 1.6.0的reflect包如下圖:

該類下的幾個主要類和接口

三、JAVA反射機制提供了什么功能

=========================================

Java反射機制提供如下功能(用途):

在運行時判斷任意一個對象所屬的類

在運行時構造任意一個類的對象

在運行時判段任意一個類所具有的成員變量和方法

在運行時調用任一個對象的方法

在運行時創(chuàng)建新類對象

=======================================

一個對象的創(chuàng)建分三步完成:

1、加載類到內存;
2、靜態(tài)資源初始化;
3、創(chuàng)建對象;

一個類對應一個字節(jié)碼文件*.class,反射研究的就是字節(jié)碼文件;一個字節(jié)碼文件中主要包含類的成員變量、方法、構造方法;通過該字節(jié)碼文件可以獲取該類的相關信息。同一個字節(jié)碼文件可以構建多個對象;

//類的字節(jié)碼文件 MyA a1=new MyA(); //獲得該類的字節(jié)碼文件 Class clazz=a1.getClass();

對象類型有字節(jié)碼文件,基礎的數據類型也有相應的字節(jié)碼文件。

int.class void.class

在使用Java的反射功能時,基本首先都要獲取類的Class字節(jié)碼對象,再通過Class對象獲取其他的對象。

1、獲取類的Class字節(jié)碼對象

Class 類的實例表示正在運行的 Java 應用程序中的類和接口。獲取類的Class對象有多種方式:

2、獲取類的屬性

可以通過反射機制得到某個類的某個屬性,然后可以改變對應于這個類的某個實例的該屬性值。JAVA 的Class<T>類提供了幾個方法獲取類的屬性。

public Field getField(String name)

返回某類一個public修飾的成員變量(public,包括父類中定義);

public Field[] getFields()

返回一個數組,數組中包含某類下的public修飾的所有成員變量(public,包括父類中定義);

public Field getDeclaredField(String name)

返回某類一個private修飾的成員變量(private,不包括父類中定義);

public Field[] getDeclaredFields()

返回一個數組,數組中包含某類下的所有private修飾的成員變量(private,不包括父類中定義);

3、獲取類的方法

通過反射機制得到某個類的某個方法,然后可以調用對應于這個類的某個實例的該方法,Class<T>類提供了幾個方法獲取類的方法。

public Method getMethod(String name,Class<?>... parameterTypes)

通過方法名和方法的入參得到一個某類下的public修飾的Method方法對象(public,包括父類中定義);

public Method[] getMethods()

得到某類下的public修飾的所有Method方法對象(public,包括父類定義的)

public MethodgetDeclaredMethod(Stringname,Class<?>... parameterTypes)

通過方法名和方法的入參得到一個某類下的private修飾的Method方法對象(private,不包括父類中定義);;

public Method[] getDeclaredMethods()

得到某類下的private修飾的所有Method方法對象(private,不包括父類定義的)

通過反射獲得類的方法(public)MyA m1=new MyA();Class clazz=m1.getClass();//方法名,入參 clazz.getMethod("setAge",int.class);//獲得方法名之后,如何調用該方法(對象,入參) setAge.invoke(m1,23);//調用m1下的該方法m1.getAge();//23注意: setAge.invoke(null,23);當前類下的不依賴對象的方法(靜態(tài)方法)要被執(zhí)行;

4、獲取類的Constructor構造方法

通過反射機制得到某個類的構造器,然后可以調用該構造器創(chuàng)建該類的一個實例Class<T> 類提供了幾個方法獲取類的構造器。

public Constructor<T> getConstructor(Class<?>... parameterTypes)

通過構造方法的入參返回一個有相應入參的 Constructor 對象(public,包括父類中定義);

public Constructor<?>[] getConstructors()

返回一個數組,該數組中包含該類下的所有構造方法(public,包括父類中定義);

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

通過構造方法的入參返回一個有相應入參的 Constructor 對象(private,不包括父類中定義);

public Constructor<?>[] getDeclaredConstructors()

返回一個數組,該數組中包含該類下的所有構造方法(private,不包括父類中定義);

5、創(chuàng)建類的實例

通過反射機制創(chuàng)建類的實例,有幾種方法可以創(chuàng)建

調用無自變量的構造器

1、調用類的Class對象的newInstance方法,該方法會調用對象的默認構造器,如果沒有默認構造器,會調用失敗(所以,在實際應用中用到這種方法時,如果要重寫一個類的帶參數的構造方法,就一定要把不帶參數的構造方法顯式定義出來).

Class<?> classType = ExtendType.class; Object inst = classType.newInstance();System.out.println(inst); 輸出: Type:Default Constructor ExtendType:Default Constructor com.quincy.ExtendType@d80be3

2、調用默認Constructor對象的newInstance方法

Class<?> classType = ExtendType.class; Constructor<?> constructor1 = classType.getConstructor(); Object inst = constructor1.newInstance(); System.out.println(inst); 輸出: Type:Default Constrructor ExtendType:Default Constru com.quincy.ExtendType@1006d756d75

調用帶參數構造器

3、調用帶參數Constructor對象的newInstance方法

Constructor<?> constructor2 =classType.getDeclaredConstructor(int.class, String.class);Object inst = constructor2.newInstance(1, "123");System.out.println(inst);輸出:Type:Default Constructor ExtendType:Constructor with parameters com.quincy.ExtendType@15e83f9

6、調用類的函數

通過反射獲取類Method方法對象,調用Field的Invoke方法調用函數(方法)。

參見上面獲取類的方法

7、設置/獲取類的屬性值

通過反射獲取類的成員變量,調用成員變量的方法設置或獲取值;

MyA m1=new MyA("zhangsan"); MyA m2=new MyA("lisi");Class clazz=m1.getClass(); //獲得MyA類的所有成員變量 Field[] fields=clazz.getFields();//獲得MyA下名為"name"的成員變量 Field nameField=clazz.getField("name"); 以上適用于用public修飾的成員變量,如果成員變量使用private修飾的則拿不到;要用以下方法://nameField是一個引用(地址) Field nameField=clazz.getDeclaredField("name"); //如果該成員變量使用private修飾的,要加下面一句 nameField.setAccessible("true");------------------要指定獲得哪一個對象上的數據 //獲得m1中nameField對應的成員變量的名字 String name=nameField.get(m1);//獲得m2中nameField對應的成員變量的名字 String name=nameField.get(m2);--------------------為m1中的成員變量設值 nameField.set(m1,"張三");//覆蓋掉zhangsan //獲得nameField對應的成員變量的類型 nameField.getType();

四、動態(tài)創(chuàng)建代理類

代理模式:代理模式的作用=為其他對象提供一種代理以控制對這個對象的訪問。

代理模式的角色:

抽象角色:聲明真實對象和代理對象的共同接口
代理角色:代理角色內部包含有真實對象的引用,從而可以操作真實對象。

真實角色:代理角色所代表的真實對象,是我們最終要引用的對象。

動態(tài)代理:

java.lang.reflect.Proxy
Proxy 提供用于創(chuàng)建動態(tài)代理類和實例的靜態(tài)方法,它還是由這些方法創(chuàng)建的所有動態(tài)代理類的超類
InvocationHandler
是代理實例的調用處理程序實現的接口,每個代理實例都具有一個關聯的調用處理程序。對代理實例調用方法時,將對方法調用進行編碼并將其指派到它的調用處理程序的 invoke 方法。

動態(tài)Proxy是這樣的一種類:

它是在運行生成的類,在生成時你必須提供一組Interface給它,然后該class就宣稱它實現了這些interface。你可以把該class的實例當作這些interface中的任何一個來用。當然,這個Dynamic Proxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。

在使用動態(tài)代理類時,我們必須實現ndler接口

有關代理模式的具體了解請參看本人設計模式相關文章。

補充:

1、
`MyA a1=new MyA();

Class clazz=a1.getClass();

MyA a2=new MyA();

if(a1 == a2)…//不相等,比較的是引用(地址)

if(clazz == a2.getClass())…//相等(是由同一個字節(jié)碼文

件構建的,都相當于:new MyA().getClass())
`

2、拿到一個字節(jié)碼文件之后,如何判斷它是一個對象類型還是普通的數據類型

//基礎數據類型返回true,對象類型返回false clazz.isPrimitive();//falseint.class.inPrimitive();//true

總結

以上是生活随笔為你收集整理的详解Java反射机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。