一、什么是JAVA的反射機(jī)制
Java反射是Java被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語言的一個(gè)關(guān)鍵性質(zhì)酌伊。這個(gè)機(jī)制允許程序在運(yùn)行時(shí)透過Reflection? APIs取得任何一個(gè)已知名稱的class的內(nèi)部信息漫萄,包括其modifiers(諸如public,?static? 等)、superclass(例如Object)盈匾、實(shí)現(xiàn)之interfaces(例如Cloneable)腾务,也包括fields和methods的所有信息,并可于運(yùn)行時(shí)改變fields內(nèi)容或喚起methods削饵。
Java反射機(jī)制容許程序在運(yùn)行時(shí)加載岩瘦、探知、使用編譯期間完全未知的classes窿撬。
換言之启昧,Java可以加載一個(gè)運(yùn)行時(shí)才得知名稱的class,獲得其完整結(jié)構(gòu)劈伴。
二密末、JDK中提供的Reflection?API
Java反射相關(guān)的API在包java.lang.reflect中,JDK?1.6.0的reflect包如下圖:
#FormatImgID_0#
Member接口該接口可以獲取有關(guān)類成員(域或者方法)后者構(gòu)造函數(shù)的信息跛璧。
AccessibleObject類該類是域(field)對(duì)象严里、方法(method)對(duì)象、構(gòu)造函數(shù)(constructor)對(duì)象的基礎(chǔ)類追城。它提供了將反射的對(duì)象標(biāo)記為在使用時(shí)取消默認(rèn)? Java?語言訪問控制檢查的能力刹碾。
Array類該類提供動(dòng)態(tài)地生成和訪問JAVA數(shù)組的方法。
Constructor類提供一個(gè)類的構(gòu)造函數(shù)的信息以及訪問類的構(gòu)造函數(shù)的接口座柱。
Field類提供一個(gè)類的域的信息以及訪問類的域的接口迷帜。
Method類提供一個(gè)類的方法的信息以及訪問類的方法的接口物舒。
Modifier類提供了?static?方法和常量,對(duì)類和成員訪問修飾符進(jìn)行解碼戏锹。
Proxy類提供動(dòng)態(tài)地生成代理類和類實(shí)例的靜態(tài)方法冠胯。
三、JAVA反射機(jī)制提供了什么功能
Java反射機(jī)制提供如下功能:
在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類
在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象
在運(yùn)行時(shí)判段任意一個(gè)類所具有的成員變量和方法
在運(yùn)行時(shí)調(diào)用任一個(gè)對(duì)象的方法
在運(yùn)行時(shí)創(chuàng)建新類對(duì)象
在使用Java的反射功能時(shí)景用,基本首先都要獲取類的Class對(duì)象涵叮,再通過Class對(duì)象獲取其他的對(duì)象。
這里首先定義用于測(cè)試的類:
+?View?Code
1伞插、獲取類的Class對(duì)象
Class?類的實(shí)例表示正在運(yùn)行的?Java?應(yīng)用程序中的類和接口割粮。獲取類的Class對(duì)象有多種方式:
調(diào)用getClassBoolean?var1?=?true;
Class?classType2?=?var1.getClass();
System.out.println(classType2);
輸出:class?java.lang.Boolean
運(yùn)用.class?語法Class?classType4?=?Boolean.class;
System.out.println(classType4);
輸出:class?java.lang.Boolean
運(yùn)用static?method?Class.forName()Class?classType5?=? Class.forName("java.lang.Boolean");
System.out.println(classType5);
輸出:class?java.lang.Boolean
運(yùn)用primitive?wrapper?classes的TYPE?語法
這里返回的是原生類型,和Boolean.class返回的不同Class?classType3?=?Boolean.TYPE;
System.out.println(classType3);
輸出:boolean
2媚污、獲取類的Fields
可以通過反射機(jī)制得到某個(gè)類的某個(gè)屬性舀瓢,然后改變對(duì)應(yīng)于這個(gè)類的某個(gè)實(shí)例的該屬性值。JAVA?的Class類提供了幾個(gè)方法獲取類的屬性耗美。
public?FieldgetField(String?name)返回一個(gè)?Field?對(duì)象京髓,它反映此?Class? 對(duì)象所表示的類或接口的指定公共成員字段
public?Field[]?getFields()返回一個(gè)包含某些?Field?對(duì)象的數(shù)組,這些對(duì)象反映此?Class? 對(duì)象所表示的類或接口的所有可訪問公共字段
public?FieldgetDeclaredField(Stringname)返回一個(gè)?Field?對(duì)象商架,該對(duì)象反映此?Class? 對(duì)象所表示的類或接口的指定已聲明字段
public?Field[]?getDeclaredFields()返回?Field?對(duì)象的一個(gè)數(shù)組堰怨,這些對(duì)象反映此?Class? 對(duì)象所表示的類或接口所聲明的所有字段
+?View?Code
輸出:
public?int?com.quincy.ExtendType.pubIntExtendField
public?java.lang.String?com.quincy.ExtendType.pubStringExtendField
public?int?com.quincy.Type.pubIntField
public?java.lang.String?com.quincy.Type.pubStringField
public?int?com.quincy.ExtendType.pubIntExtendField
public?java.lang.String?com.quincy.ExtendType.pubStringExtendField
private?int?com.quincy.ExtendType.prvIntExtendField
可見getFields和getDeclaredFields區(qū)別:
getFields返回的是申明為public的屬性,包括父類中定義蛇摸,
getDeclaredFields返回的是指定類定義的所有定義的屬性备图,不包括父類的。
3赶袄、獲取類的Method
通過反射機(jī)制得到某個(gè)類的某個(gè)方法揽涮,然后調(diào)用對(duì)應(yīng)于這個(gè)類的某個(gè)實(shí)例的該方法
Class類提供了幾個(gè)方法獲取類的方法。
public?MethodgetMethod(String?name,?Class...?parameterTypes)返回一個(gè)?Method? 對(duì)象饿肺,它反映此?Class?對(duì)象所表示的類或接口的指定公共成員方法
public?Method[]?getMethods()返回一個(gè)包含某些?Method?對(duì)象的數(shù)組蒋困,這些對(duì)象反映此?Class? 對(duì)象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共?member?方法
public?MethodgetDeclaredMethod(String?name,Class...?parameterTypes)返回一個(gè)? Method?對(duì)象,該對(duì)象反映此?Class?對(duì)象所表示的類或接口的指定已聲明方法
public?Method[]?getDeclaredMethods()返回?Method?對(duì)象的一個(gè)數(shù)組敬辣,這些對(duì)象反映此?Class? 對(duì)象表示的類或接口聲明的所有方法雪标,包括公共、保護(hù)溉跃、默認(rèn)(包)訪問和私有方法汰聋,但不包括繼承的方法
+?View?Code
輸出:
public?void?com.quincy.ExtendType.setIntExtendField(int)
public?int?com.quincy.ExtendType.getIntExtendField()
public?void?com.quincy.Type.setIntField(int)
public?int?com.quincy.Type.getIntField()
public?final?native?void?java.lang.Object.wait(long)?throws? java.lang.InterruptedException
public?final?void?java.lang.Object.wait()?throws? java.lang.InterruptedException
public?final?void?java.lang.Object.wait(long,int)?throws? java.lang.InterruptedException
public?boolean?java.lang.Object.equals(java.lang.Object)
public?java.lang.String?java.lang.Object.toString()
public?native?int?java.lang.Object.hashCode()
public?final?native?java.lang.Class?java.lang.Object.getClass()
public?final?native?void?java.lang.Object.notify()
public?final?native?void?java.lang.Object.notifyAll()
private?void?com.quincy.ExtendType.Log(java.lang.String)
public?void?com.quincy.ExtendType.setIntExtendField(int)
public?int?com.quincy.ExtendType.getIntExtendField()
4、獲取類的Constructor
通過反射機(jī)制得到某個(gè)類的構(gòu)造器喊积,然后調(diào)用該構(gòu)造器創(chuàng)建該類的一個(gè)實(shí)例
Class類提供了幾個(gè)方法獲取類的構(gòu)造器烹困。
public?Constructor?getConstructor(Class...?parameterTypes)返回一個(gè)? Constructor?對(duì)象,它反映此?Class?對(duì)象所表示的類的指定公共構(gòu)造方法
public?Constructor[]?getConstructors()返回一個(gè)包含某些?Constructor?對(duì)象的數(shù)組乾吻,這些對(duì)象反映此? Class?對(duì)象所表示的類的所有公共構(gòu)造方法
public?Constructor?getDeclaredConstructor(Class...? parameterTypes)返回一個(gè)?Constructor?對(duì)象髓梅,該對(duì)象反映此?Class?對(duì)象所表示的類或接口的指定構(gòu)造方法
public?Constructor[]?getDeclaredConstructors()返回?Constructor? 對(duì)象的一個(gè)數(shù)組拟蜻,這些對(duì)象反映此?Class?對(duì)象表示的類聲明的所有構(gòu)造方法。它們是公共枯饿、保護(hù)酝锅、默認(rèn)(包)訪問和私有構(gòu)造方法
+?View?Code
5、新建類的實(shí)例
通過反射機(jī)制創(chuàng)建新類的實(shí)例奢方,有幾種方法可以創(chuàng)建
調(diào)用無自變量ctor1搔扁、調(diào)用類的Class對(duì)象的newInstance方法,該方法會(huì)調(diào)用對(duì)象的默認(rèn)構(gòu)造器蟋字,如果沒有默認(rèn)構(gòu)造器稿蹲,會(huì)調(diào)用失敗.
Class?classType?=?ExtendType.class;
Object?inst?=?classType.newInstance();
System.out.println(inst);
輸出:
Type:Default?Constructor
ExtendType:Default?Constructor
com.quincy.ExtendType@d80be3
2、調(diào)用默認(rèn)Constructor對(duì)象的newInstance方法
Class?classType?=?ExtendType.class;
Constructor?constructor1?=?classType.getConstructor();
Object?inst?=?constructor1.newInstance();
System.out.println(inst);
輸出:
Type:Default?Constructor
ExtendType:Default?Constructor
com.quincy.ExtendType@1006d75
調(diào)用帶參數(shù)ctor3鹊奖、調(diào)用帶參數(shù)Constructor對(duì)象的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苛聘、調(diào)用類的函數(shù)
通過反射獲取類Method對(duì)象,調(diào)用Field的Invoke方法調(diào)用函數(shù)忠聚。
+?View?Code
7设哗、設(shè)置/獲取類的屬性值
通過反射獲取類的Field對(duì)象,調(diào)用Field方法設(shè)置或獲取值
+?View?Code
+?View?Code
四两蟀、動(dòng)態(tài)創(chuàng)建代理類
代理模式:代理模式的作用=為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問网梢。
代理模式的角色:
抽象角色:聲明真實(shí)對(duì)象和代理對(duì)象的共同接口
代理角色:代理角色內(nèi)部包含有真實(shí)對(duì)象的引用,從而可以操作真實(shí)對(duì)象赂毯。
真實(shí)角色:代理角色所代表的真實(shí)對(duì)象战虏,是我們最終要引用的對(duì)象。
動(dòng)態(tài)代理:
java.lang.reflect.ProxyProxy?提供用于創(chuàng)建動(dòng)態(tài)代理類和實(shí)例的靜態(tài)方法欢瞪,它還是由這些方法創(chuàng)建的所有動(dòng)態(tài)代理類的超類
InvocationHandler是代理實(shí)例的調(diào)用處理程序? 實(shí)現(xiàn)的接口,每個(gè)代理實(shí)例都具有一個(gè)關(guān)聯(lián)的調(diào)用處理程序徐裸。對(duì)代理實(shí)例調(diào)用方法時(shí)遣鼓,將對(duì)方法調(diào)用進(jìn)行編碼并將其指派到它的調(diào)用處理程序的?invoke?方法。
動(dòng)態(tài)Proxy是這樣的一種類:
它是在運(yùn)行生成的類重贺,在生成時(shí)你必須提供一組Interface給它骑祟,然后該class就宣稱它實(shí)現(xiàn)了這些interface。你可以把該class的實(shí)例當(dāng)作這些interface中的任何一個(gè)來用气笙。當(dāng)然次企,這個(gè)Dynamic? Proxy其實(shí)就是一個(gè)Proxy,它不會(huì)替你作實(shí)質(zhì)性的工作潜圃,在生成它的實(shí)例時(shí)你必須提供一個(gè)handler缸棵,由它接管實(shí)際的工作。
在使用動(dòng)態(tài)代理類時(shí)谭期,我們必須實(shí)現(xiàn)InvocationHandler接口
步驟:
1堵第、定義抽象角色
public?interface?Subject?{
public?void?Request();
}
2吧凉、定義真實(shí)角色
public?class?RealSubject?implements?Subject?{
@Override
public?void?Request()?{
//?TODO?Auto-generated?method?stub
System.out.println("RealSubject");
}
}
3、定義代理角色
public?class?DynamicSubject?implements?InvocationHandler?{
private?Object?sub;
public?DynamicSubject(Object?obj){
this.sub?=?obj;
}
@Override
public?Object?invoke(Object?proxy,?Method?method,?Object[]?args)
throws?Throwable?{
//?TODO?Auto-generated?method?stub
System.out.println("Method:"+?method?+?",Args:"?+?args);
method.invoke(sub,?args);
return?null;
}
}
4踏志、通過Proxy.newProxyInstance構(gòu)建代理對(duì)象
RealSubject?realSub?=?new?RealSubject();
InvocationHandler?handler?=?new?DynamicSubject(realSub);
Class?classType?=?handler.getClass();
Subject?sub?=? (Subject)Proxy.newProxyInstance(classType.getClassLoader(),
realSub.getClass().getInterfaces(),?handler);
System.out.println(sub.getClass());
5阀捅、通過調(diào)用代理對(duì)象的方法去調(diào)用真實(shí)角色的方法。
sub.Request();
輸出:
class?$Proxy0?新建的代理對(duì)象针余,它實(shí)現(xiàn)指定的接口
Method:public?abstract?void?DynamicProxy.Subject.Request(),Args:null
RealSubject?調(diào)用的真實(shí)對(duì)象的方法
Java交流裙:109--1181--875
java-數(shù)據(jù)類型
http://www.makeru.com.cn/live/1394_203.html?s=156461
常用工具類
http://www.makeru.com.cn/live/1394_253.html?s=156461
javaweb后端開發(fā)案例