學(xué)習(xí)目的
了解反射的概念與作用意義
掌握java提供的反射機(jī)制使用到的包和類(lèi)
了解反射機(jī)制的實(shí)現(xiàn)原理與Spring框架的結(jié)合
一.反射
概念
在日常開(kāi)發(fā)中,通常的開(kāi)發(fā)步驟是:程序員建立項(xiàng)目 --> 編寫(xiě)源代碼 --> 編譯得到.class字節(jié)碼文件 --> java虛擬機(jī)JVM加載字節(jié)碼文件 --> 執(zhí)行運(yùn)行。
而反射的步驟則是:通過(guò)編譯好的字節(jié)碼文件 --> 創(chuàng)建字節(jié)碼對(duì)象 --> 對(duì)編譯后的文件進(jìn)行操作,操作包括創(chuàng)建實(shí)例對(duì)象、讀取或修改對(duì)象屬性、獲取和執(zhí)行對(duì)象方法等。
實(shí)質(zhì)
反射對(duì)字節(jié)碼文件內(nèi)容的操作都基于"字節(jié)碼對(duì)象",而對(duì)實(shí)例對(duì)象、屬性、方法等也有專(zhuān)屬的反射"類(lèi)"對(duì)象。
原則
一切皆對(duì)象。
1.1 java.lang.reflect反射包
定義
提供用于獲取類(lèi)和對(duì)象的反射信息(字節(jié)碼信息) 的類(lèi)和接口。
實(shí)質(zhì)
提供操作字節(jié)碼文件的"操作對(duì)象"。
反射常用接口
Type:Java中所有類(lèi)型的公共高級(jí)接口
反射常用類(lèi)
Class:所有類(lèi)或接口的"類(lèi)型";
Constructor:構(gòu)造器類(lèi);
Field:屬性類(lèi);
Method:方法類(lèi);
Modifier:修飾符類(lèi);
反射最重要方法
Object invoke(Object obj, Object... args) :該方法屬于Method類(lèi)中的方法,obj為字節(jié)碼對(duì)象創(chuàng)建出的一個(gè)實(shí)例對(duì)象;使用Method對(duì)象調(diào)用該方法意為 調(diào)用obj對(duì)象的該Method方法,并且方法的參數(shù)為...args。
// 使用反射機(jī)制來(lái)調(diào)用一個(gè)對(duì)象的方法
// 創(chuàng)建字節(jié)碼對(duì)象
Class userClass = Class.forName("com.java.service.User");
// 通過(guò)字節(jié)碼反射創(chuàng)建實(shí)例對(duì)象
Object obj = userServiceClass.newInstance();
// 獲取字節(jié)碼對(duì)象中的Method對(duì)象(實(shí)則為一個(gè)方法),通過(guò)"方法名"和參數(shù)的類(lèi)型(重載根據(jù)參數(shù)列表區(qū)分)
Method loginMethod = userClass.getDeclaredMethod("login", String.class, String.class);
//Method loginMethod = userClass.getDeclaredMethod("login", int.class);
// 調(diào)用方法4要素:Method方法對(duì)象,實(shí)例對(duì)象Obj,參數(shù),返回值
// 通過(guò)Method對(duì)象.invoke()執(zhí)行obj對(duì)象的Method方法,參數(shù)為...
Object retValue = loginMethod.invoke(obj, "admin","123123");
System.out.println(retValue);
1.2 java.lang.reflect.Type接口
定義
Type 是Java中所有"類(lèi)型"的公共高級(jí)接口,包括原始類(lèi)型、參數(shù)化類(lèi)型、數(shù)組類(lèi)型、類(lèi)型變量和基本類(lèi)型等。
實(shí)質(zhì)
"數(shù)據(jù)類(lèi)型" ,包括類(lèi)的類(lèi)型、參數(shù)的類(lèi)型、元素的類(lèi)型、返回值的類(lèi)型等等。
1.3 java.lang.Class<T>類(lèi)
定義
Class類(lèi)表示Java應(yīng)用程序中的類(lèi)和接口,包括我們自定義的"class類(lèi)" 和 "interface接口"等。Class類(lèi)用于反射指的是字節(jié)碼文件內(nèi)容中代表的"類(lèi)型",如public類(lèi)的字節(jié)碼文件名代表的就是該"類(lèi)",是一個(gè)Class。Class還實(shí)現(xiàn)了Type接口。
實(shí)質(zhì)
Class類(lèi)代表所有的"類(lèi)" 和 "接口"。
特點(diǎn)
Class沒(méi)有公共構(gòu)造方法(只有一個(gè)private的構(gòu)造 類(lèi)加載器的構(gòu)造器),Class對(duì)象是在加載類(lèi)時(shí)由Java虛擬機(jī)以及 通過(guò)調(diào)用類(lèi)加載器中的defineClass方法自動(dòng)構(gòu)造的。
常用方法
String toString():將該Class對(duì)象轉(zhuǎn)換為字符串,返回的字符串表示形式為 "class" / "interface" + 空格 + 該Class對(duì)象代表的完整類(lèi)名;
Class<?> forName(String className) :返回 給定字符串名的類(lèi)或接口相關(guān)的 Class字節(jié)碼對(duì)象,采用默認(rèn)的類(lèi)加載器;
Class<?> forName(String name, boolean initialize,ClassLoader loader):返回 給定字符串名的類(lèi)或接口相關(guān)的 Class字節(jié)碼對(duì)象,采用指定的類(lèi)加載器,并有可能初始化該字節(jié)碼對(duì)象;
T newInstance() :創(chuàng)建此Class字節(jié)碼對(duì)象所代表的類(lèi)的一個(gè)新實(shí)例;
boolean isInstance(Object obj):判斷obj對(duì)象是否 是該Class字節(jié)碼對(duì)象代表的類(lèi)的一個(gè)實(shí)例;
boolean isInterface():判定該Class字節(jié)碼對(duì)象是否代表一個(gè)接口類(lèi)型;
boolean isArray():判定該Class字節(jié)碼對(duì)象是否代表一個(gè)數(shù)組類(lèi)型;
boolean isPrimitive():判定該Class字節(jié)碼對(duì)象是否代表一個(gè)基本類(lèi)型;
boolean isAnnotation():判定該Class字節(jié)碼對(duì)象是否代表一個(gè)注釋類(lèi)型;
String getName() :返回該Class字節(jié)碼對(duì)象所代表類(lèi)的全(路徑)類(lèi)名;
String getSimpleName():返回該Class字節(jié)碼對(duì)象所代表類(lèi)的簡(jiǎn)類(lèi)名;
ClassLoader getClassLoader():返回加載該Class字節(jié)碼對(duì)象的類(lèi)加載器;
Class<? super T> getSuperclass():返回該Class字節(jié)碼對(duì)象所代表的類(lèi)的父類(lèi)或父接口;
Class<?>[] getInterfaces():返回該Class字節(jié)碼對(duì)象所代表的類(lèi)所實(shí)現(xiàn)的所有接口,使用數(shù)組存儲(chǔ);
int getModifiers() :返回該Class字節(jié)碼對(duì)象所代表的類(lèi)的修飾符,返回的是表示該類(lèi)修飾符的int數(shù)(需要配合Modifier類(lèi)的toString()方法將其轉(zhuǎn)換為字符串);
Class<?> getDeclaringClass():若該Class字節(jié)碼對(duì)象是另一個(gè)類(lèi)或接口的成員,返回該Class字節(jié)碼對(duì)象的聲明類(lèi)或接口;
boolean isAnonymousClass():判斷該Class字節(jié)碼對(duì)象底層是否是內(nèi)部類(lèi);
boolean isLocalClass():判斷該Class字節(jié)碼對(duì)象底層是否是native本地類(lèi);
Field getField(String name) :返回一個(gè)Field對(duì)象,代表該Class字節(jié)碼對(duì)象所代表的類(lèi)或接口的"公共"成員屬性;
Method getMethod(String name, Class<?>... parameterTypes) :返回一個(gè)Method對(duì)象,根據(jù)指定的方法名和參數(shù)類(lèi)型查找返回;
Constructor<T> getConstructor(Class<?>... parameterTypes) :返回一個(gè)Constructor對(duì)象,根據(jù)參數(shù)類(lèi)型查找返回(僅返回public構(gòu)造器);
Field[] getDeclaredFields() :返回一個(gè)Field數(shù)組對(duì)象,代表該Class字節(jié)碼對(duì)象所代表的類(lèi)或接口的所有成員屬性(包括公開(kāi)的私有的);
Method[] getDeclaredMethods() :返回一組 包含了該字節(jié)碼對(duì)象所有的Method方法對(duì)象;
Constructor<?>[] getDeclaredConstructors():返回一組 Constructor對(duì)象,包含了該字節(jié)碼對(duì)象中的所有、構(gòu)造器對(duì)象;
Field getDeclaredField(String name) :返回一個(gè) Field對(duì)象,根據(jù)指定的字段屬性名來(lái)查找返回;
Method getDeclaredMethod(mName,pType...) :返回一個(gè)Method方法對(duì)象,根據(jù)方法名、參數(shù)類(lèi)型作為區(qū)分;
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回一個(gè)任意修飾符的Constructor對(duì)象,根據(jù)參數(shù)類(lèi)型查找返回;
java.net.URL getResource(String name):
T cast(Object obj):將指定obj對(duì)象強(qiáng)制轉(zhuǎn)換成Class字節(jié)碼對(duì)象所代表的類(lèi)。
代碼示例
//創(chuàng)建字節(jié)碼對(duì)象
Class c = Class.forName("com.yry.pratice.reflection.bean.User");
System.out.println(c);
//將字節(jié)碼對(duì)象c換成字符串輸出:Class或Interface 全類(lèi)名
String s = c.toString();
System.out.println(s);
//獲取字節(jié)碼對(duì)象所代表類(lèi)的名稱(chēng)
String name = c.getName();//全類(lèi)名
System.out.println(name);//com.yry.pratice.reflection.bean.User
String simpleName = c.getSimpleName();//簡(jiǎn)類(lèi)名
System.out.println(simpleName);//User
//由字節(jié)碼對(duì)象 反射創(chuàng)建 實(shí)例對(duì)象s
Object instance = c.newInstance();
System.out.println(instance);//輸出instance.toString()的執(zhí)行結(jié)果
//判斷指定obj對(duì)象是否 該字節(jié)碼對(duì)象的一個(gè)實(shí)例
Object oo = new Object();
boolean b = c.isInstance(oo);
System.out.println(b);
//獲取加載該字節(jié)碼對(duì)象的類(lèi)加載器
ClassLoader classLoader = c.getClassLoader();
System.out.println(classLoader);//
//獲取該字節(jié)碼對(duì)象的修飾符--public公開(kāi)的修飾符
int modifiers = c.getModifiers();//不同的int值代表不同的修飾符
System.out.println(modifiers);//1
//將int類(lèi)型修飾符 轉(zhuǎn)換成 String字符串表示
String s1 = Modifier.toString(modifiers);
System.out.println(s1);//1對(duì)應(yīng)public
1.4 java.lang.reflect.Constructor<T>構(gòu)造器類(lèi)
定義
Constructor提供關(guān)于類(lèi)的單個(gè)構(gòu)造方法的信息 以及對(duì)它的訪問(wèn)權(quán)限。
實(shí)質(zhì)
Constructor在反射中指的是Class字節(jié)碼對(duì)象所代表類(lèi)的構(gòu)造器。
常用方法
Class<T> getDeclaringClass() :返回Class字節(jié)碼對(duì)象,返回聲明此Constructor構(gòu)造器 表示的Class"類(lèi)"對(duì)象;
String getName() :返回此構(gòu)造方法的名稱(chēng);
int getModifiers() :返回此構(gòu)造方法的修飾符(需要配合Modifier類(lèi)的toString()方法將其轉(zhuǎn)換成字符串);
Class<?>[] getParameterTypes():按聲明順序返回此構(gòu)造方法參數(shù)列表中的 參數(shù)類(lèi)型數(shù)組;
int getParameterCount() :返回此構(gòu)造方法參數(shù)列表中的 參數(shù)的個(gè)數(shù);
Class<?>[] getExceptionTypes():返回一組 此構(gòu)造方法拋出的所有異常類(lèi)型數(shù)組;
boolean equals(Object obj):將此Constructor對(duì)象與obj對(duì)象進(jìn)行比較是否相同,如果兩個(gè)對(duì)象由相同的類(lèi)聲明并且具有相同的形參類(lèi)型則是相同的。
int hashCode():返回此Constructor的哈希碼,與此Constructor所代表的類(lèi)的哈希碼相同;
String toString():返回描述此構(gòu)造器的字符串,構(gòu)造方法唯一可能的修飾符是訪問(wèn)修飾符public、protected或private;
T newInstance(Object ... initargs):通過(guò)此構(gòu)造方法所代表的類(lèi)來(lái) 創(chuàng)建的新對(duì)象;
boolean isVarArgs():判斷此構(gòu)造方法是否帶可變數(shù)量的參數(shù);
T getAnnotation(Class<T> annotation):如果此構(gòu)造器上 存在指定annotation.Class 類(lèi)型的注釋?zhuān)祷剡@些注釋?zhuān)?/li>
Annotation[] getDeclaredAnnotations():返回一組 直接存在于此構(gòu)造器上的所有注釋?zhuān)?/li>
代碼示例
//創(chuàng)建字節(jié)碼對(duì)象
Class c = Class.forName("com.yry.pratice.reflection.bean.User");
//獲取該字節(jié)碼對(duì)象的構(gòu)造器
Constructor[] constructors = c.getConstructors();
for (Constructor con:constructors) {
System.out.println(con.getModifiers());//構(gòu)造器的修飾符
System.out.println(con.getDeclaringClass());//聲明該構(gòu)造器的類(lèi)
System.out.println(con.getName());//構(gòu)造器的名稱(chēng)
//獲取構(gòu)造器的參數(shù)類(lèi)型數(shù)組
Class[] parameterTypes = con.getParameterTypes();
for (Class cas: parameterTypes) {
System.out.println(cas.getClass());//構(gòu)造器參數(shù)的類(lèi)型
System.out.println(cas.getSimpleName());//構(gòu)造器參數(shù)的名稱(chēng)
}
}
1.5 java.lang.reflect.Field屬性類(lèi)<重要掌握>
定義
Field提供有關(guān) 類(lèi)或接口的單個(gè)字段的信息,以及對(duì)它的動(dòng)態(tài)訪問(wèn)權(quán)限。反射的字段可能是一個(gè)類(lèi)字段(靜態(tài)字段)或?qū)嵗侄巍?/li>
實(shí)質(zhì)
Field指的是Class字節(jié)碼對(duì)象所代表的類(lèi)中的普通字段或?qū)傩?,每一個(gè)字段或?qū)傩远际且粋€(gè)對(duì)象。
常用方法
Class<?> getDeclaringClass() :返回聲明此Field對(duì)象所表示字段的類(lèi)或接口 的Class對(duì)象;
String getName() :返回此Field對(duì)象所表示字段的名稱(chēng);
int getModifiers():返回此Field對(duì)象所表示字段的修飾符;
boolean isEnumConstant():判斷該Filed對(duì)象所表示的字段是否是枚舉類(lèi)型的元素;
Class<?> getType() :返回此Field對(duì)象所表示字段的數(shù)據(jù)類(lèi)型;
boolean equals(Object obj):判斷兩個(gè)字段對(duì)象obj與此Filed對(duì)象比較是否相同,如果兩個(gè)對(duì)象由相同的類(lèi)聲明并且具有相同的名稱(chēng)和類(lèi)型,則相同的;
int hashCode():返回此Field對(duì)象所表示字段的哈希地址;
String toString():返回該Field對(duì)象所表示字段的字符串表示形式(原字段的定義格式);
Object get(Object obj) :從obj對(duì)象中獲取 此Field表示的字段的值(obj對(duì)象需要擁有相同F(xiàn)iled表示的字段);
boolean getBoolean(Object obj):從obj對(duì)象中 獲取一個(gè)靜態(tài)或?qū)嵗?boolean字段的值(相同用法可以獲取其他數(shù)據(jù)類(lèi)型字段的值);
void set(Object obj, Object value):將obj對(duì)象上此Field對(duì)象表示的字段 設(shè)置為指定的新值;
T getAnnotation(Class<T> annotation):如果此字段屬性上 存在指定annotation.Class 類(lèi)型的注釋?zhuān)祷剡@些注釋?zhuān)?/li>
代碼示例
//創(chuàng)建字節(jié)碼對(duì)象
Class c = Class.forName("com.yry.pratice.reflection.bean.User");
//獲取該字節(jié)碼對(duì)象的public公開(kāi)的"字段對(duì)象"
Field no = c.getField("no");//僅獲取public字段
System.out.println(no.getType().getSimpleName());//字段類(lèi)型:int
System.out.println(no.getName());//字段名/變量名:no
//獲取該字節(jié)碼對(duì)象所有的"字段對(duì)象"
Field[] declaredFields = c.getDeclaredFields();
for (Field f: declaredFields) {
System.out.println(f.getModifiers());//字段修飾符
System.out.println(f.getType());//字段數(shù)據(jù)類(lèi)型
System.out.println(f.getName());//字段名或變量名
}
1.6 java.lang.reflect.Method方法類(lèi)<重要掌握>
定義
Method提供關(guān)于 類(lèi)或接口上單獨(dú)某個(gè)方法的信息,以及如何訪問(wèn)該方法。所反映的方法可能是類(lèi)方法或?qū)嵗椒ǎòǔ橄蠓椒ǎ?/li>
實(shí)質(zhì)
Method指的是Class字節(jié)碼對(duì)象所代表的類(lèi)中的方法,即常用的自定義方法或普通方法 對(duì)象。
常用方法
Class<?> getDeclaringClass() :返回聲明此Method對(duì)象所表示方法的類(lèi)或接口 的Class對(duì)象;
String getName() :返回此Method對(duì)象所表示方法的名稱(chēng);
int getModifiers():返回此Method對(duì)象所表示方法的修飾符(需要配合Modifier類(lèi)的toString()方法將其轉(zhuǎn)換為字符串);
Class<?> getReturnType() :返回此Method對(duì)象所表示方法的返回值類(lèi)型;
Class<?>[] getParameterTypes() :返回一組 此Method對(duì)象所表示方法的參數(shù)(類(lèi)型)列表;
int getParameterCount():返回此Method對(duì)象所表示方法的 參數(shù)個(gè)數(shù);
Class<?>[] getExceptionTypes()::返回一組 此Method對(duì)象所表示方法拋出的 異常類(lèi)型;
boolean equals(Object obj):判斷兩個(gè)方法對(duì)象 obj對(duì)象與此Method對(duì)象是否相同,兩個(gè)對(duì)象代表的方法由相同的類(lèi)聲明 并具有相同的名稱(chēng)、形參類(lèi)型和返回類(lèi)型,則相同;
String toString():返回該Method對(duì)象的字符串表示形式(該Method對(duì)象所代表方法的定義格式);
boolean isVarArgs():判斷此Method對(duì)象所表示方法是否有可變數(shù)量的參數(shù);
T getAnnotation(Class<T> annotation):如果此Method對(duì)象所表示的方法上存在指定annotation.Class 類(lèi)型的注釋?zhuān)祷剡@些注釋?zhuān)?/li>
Annotation[] getDeclaredAnnotations():返回一組 直接存在于此Method對(duì)象所表示的方法上的所有注釋。
代碼示例
//創(chuàng)建字節(jié)碼對(duì)象
Class c = Class.forName("com.yry.pratice.reflection.bean.User");
//獲取該字節(jié)碼對(duì)象的"方法對(duì)象"
Method[] methods = c.getMethods();
for (Method me:methods) {
System.out.println(me.getDeclaringClass().getSimpleName());//聲明該方法的類(lèi)
System.out.println(me.getModifiers());//方法的修飾符
System.out.println(me.getReturnType());//方法的返回值類(lèi)型
System.out.println(me.getName());//方法的名稱(chēng)
Class<?>[] parameterTypes = me.getParameterTypes();//方法的參數(shù)列表
for (Class cs:parameterTypes) {
System.out.println(cs.getClass().getSimpleName());//參數(shù)類(lèi)型的名稱(chēng)
System.out.println(cs.getName());//參數(shù)的名稱(chēng)
//System.out.println(cs.getSimpleName());//參數(shù)的名稱(chēng)
}
}
1.7 java.lang.reflect.Modifier修飾符類(lèi)
定義
Modifier提供關(guān)于 類(lèi)或接口上的字段、屬性、方法的修飾符信息,Modifier類(lèi)中提供的都是static方法和常量,直接使用類(lèi)名. 調(diào)用,可以對(duì)類(lèi)和成員的訪問(wèn)修飾符進(jìn)行解碼。
特點(diǎn)
修飾符集被表示為整數(shù),用不同的位-位置 (bit position) 表示不同的修飾符,需要使用toString(位置) 方法將位置轉(zhuǎn)換為字符串(真正的修飾符表示)。
實(shí)質(zhì)
Modifier指的是Class字節(jié)碼對(duì)象所代表的類(lèi)中的修飾符,即常用的修飾符對(duì)象。
字段
int PUBLIC = 0x00000001:表示public修飾符的 int值,getModifiers()返回 1 表示該修飾符為public;
int PRIVATE = 0x00000002:表示private修飾符的 int值,getModifiers()返回 2 (以下同理:返回值是幾對(duì)應(yīng)不同的修飾符);
int PROTECTED = 0x00000004:表示protected修飾符的 int值,getModifiers()返回 4 ;
int STATIC = 0x00000008:表示static修飾符的 int值,getModifiers()返回 8 ;
int FINAL = 0x00000010:表示final修飾符的 int值,getModifiers()返回 10 ;
int SYNCHRONIZED = 0x00000020:表示synchronized修飾符的 int值,getModifiers()返回 20 ;
int VOLATILE = 0x00000040:表示volatile修飾符的 int值,getModifiers()返回 40 ;
int TRANSIENT = 0x00000080:表示transient修飾符的 int值,getModifiers()返回 80 ;
int NATIVE = 0x00000100:表示native修飾符的 int值,getModifiers()返回 100 ;
int INTERFACE = 0x00000200:表示interface修飾符的 int值,getModifiers()返回 200 ;
int ABSTRACT = 0x00000400:表示abstract修飾符的 int值,getModifiers()返回 400 。
常用方法
String toString(int mod) :將getModifiers()返回的代表指定修飾符的int值 轉(zhuǎn)換為字符串;
boolean isPublic(int mod):判斷整數(shù)參數(shù)mod是否包括public修飾符;
boolean isXxx(int mod):判斷整數(shù)參數(shù)mod是否包括Xxx修飾符。
代碼示例
//創(chuàng)建字節(jié)碼對(duì)象,獲取字節(jié)碼文件
Class c = Class.forName("com.yry.pratice.reflection.bean.User");
//獲取字節(jié)碼中 Filed字段對(duì)象
Field no = c.getField("no");
//獲取修飾Field字段的修飾符--返回的int值代表不同的修飾符
int modifiers = no.getModifiers();
System.out.println(modifiers);//返回int值為1
//將返回的int值轉(zhuǎn)換為對(duì)應(yīng)修飾符的字符串表示
String s = Modifier.toString(modifiers);
System.out.println(s);//int值為1對(duì)應(yīng)的修飾符為:Public
最后編輯于 :2020.12.15 15:41:54
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者 【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。 平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。