java反射常用方法案例詳解
1.反射概述
Java反射指的是一個(gè)機(jī)制,這種機(jī)制可以在Java程序運(yùn)行時(shí)(動態(tài))實(shí)例化對象、讀寫屬性、調(diào)用方法。
關(guān)鍵詞:運(yùn)行時(shí)
一般在我們開發(fā)程序時(shí),都知道自己具體用的什么類,直接創(chuàng)建即可。但是當(dāng)寫一些通用的功能時(shí),就不能在編譯時(shí)把具體類的類型寫死,因?yàn)槌绦蜻\(yùn)行起來后可能會有多種類型的可能,此時(shí)就需要在運(yùn)行時(shí)動態(tài)的去調(diào)用某個(gè)類的屬性和方法,這就必須通過反射來實(shí)現(xiàn)。
案例:
// 不知道調(diào)用者傳入什么類型對象。 public static String instance(Object obj) { …… }
如何知道方法的參數(shù)Object是什么類型?
一般有兩種做法:
第一種做法:是知道參數(shù)類型有哪幾種情況,可以使用instanceof運(yùn)算符進(jìn)行判斷,再利用強(qiáng)制類型轉(zhuǎn)換將其轉(zhuǎn)換成其運(yùn)行時(shí)類型的變量即可。
public static String getTypeInstanceof(Object obj){ // 學(xué)生 if (obj instanceof Student){ Student student = (Student) obj; String userType = student.getUserType("王明"); return userType; } // 老師 if (obj instanceof Teacher){ Teacher teacher = (Teacher) obj; String userType = teacher.getUserType("王明"); return userType; } return null; }
第二種做法:在編譯時(shí)根本無法預(yù)知該對象和類可能屬于哪些類,程序只依靠運(yùn)行時(shí)信息動態(tài)的來發(fā)現(xiàn)該對象和類的真實(shí)信息,這就必須使用反射。
public static String getType(Object obj) { // 通過反射獲取運(yùn)行時(shí)類 Class<?> aClass = obj.getClass(); try { // 實(shí)例化對象 Object instance = aClass.newInstance(); // 調(diào)用getUserType方法 // 匹配對象中的getUserType()方法,參數(shù)類型為String Method method02 = aClass.getMethod("getUserType", String.class); // 調(diào)用匹配的方法,傳入?yún)?shù) String invoke = (String) method02.invoke(instance, "王明"); return invoke; } catch (InstantiationException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; }
案例全部代碼:
public class Demo1 { public static void main(String[] args) { // 測試Instanceof方式 Teacher teacher = new Teacher(); String typeInstanceof = getTypeInstanceof(teacher); System.out.println(typeInstanceof); // 測試反射方式 Student student = new Student(); String type = getType(student); System.out.println(type); } public static String getTypeInstanceof(Object obj){ // 學(xué)生 if (obj instanceof Student){ Student student = (Student) obj; String userType = student.getUserType("王明"); return userType; } // 老師 if (obj instanceof Teacher){ Teacher teacher = (Teacher) obj; String userType = teacher.getUserType("王明"); return userType; } return null; } /** * 獲取用戶類型方法(老師、學(xué)生...) */ public static String getType(Object obj) { // 通過反射獲取運(yùn)行時(shí)類 Class<?> aClass = obj.getClass(); try { // 實(shí)例化對象 Object instance = aClass.newInstance(); // 調(diào)用getUserType方法 // 匹配對象中的getUserType()方法,參數(shù)類型為String Method method02 = aClass.getMethod("getUserType", String.class); // 調(diào)用匹配的方法,傳入?yún)?shù) String invoke = (String) method02.invoke(instance, "王明"); return invoke; } catch (InstantiationException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * 學(xué)生類 */ static class Student { public String getUserType(String str) { System.out.println(str); return "學(xué)生-" + str; } } /** * 老師類 */ static class Teacher { public String getUserType(String str) { System.out.println(str); return "老師-" + str; } } }
2. 反射獲取Class對象的三種方式
通過反射去使用一個(gè)類,首先我們要獲取到該類的字節(jié)碼文件對象,也就是類型為Class類型的對象。
方式一:Class.forName("包名.類名") - 常用方式
例如:Class.forName("com.kexuekt.Student");
方式二:使用類的class屬性來獲取該類對應(yīng)的Class對象
例如: Student.class;
方式三:調(diào)用對象的getClass()方法,該方法是Object類中的方法,因?yàn)槊總€(gè)類默認(rèn)繼承了Object類,所有的Java對象都可以調(diào)用該方法
例如:
Student stu = new Student();
stu.getClass();
3.反射常用方法
3.1反射獲取構(gòu)造方法
- Constructor<?>[] getDeclaredConstructors?():獲取所有構(gòu)造方法
- Constructor<?>[] getConstructors?():獲取所有public構(gòu)造方法
- Constructor<T> getConstructor?():獲取無參構(gòu)造方法
- Constructor<T> getDeclaredConstructor?(Class<?>... parameterTypes):根據(jù)參數(shù)類型獲取有參構(gòu)造方法
- 創(chuàng)建實(shí)例化對象方法 T newInstance?(Object... initargs):根據(jù)指定的構(gòu)造方法創(chuàng)建對象
3.2反射獲取成員變量
- Field[] getDeclaredFields?():獲取所有成員變量
- Field getDeclaredField?(String name):獲取單個(gè)成員變量
- Field[] getFields?():獲取所有public成員變量
- Field getField?(String name):獲取單個(gè)public成員變量
- Field類中用于給成員變量賦值的方法void set?(Object obj, Object value):給obj對象的成員變量賦值為value
私有成員變量設(shè)置值,需要取消訪問權(quán)限檢查 Field.setAccessible(true);
3.3反射獲取成員方法
- Method[] getMethods?():獲取所有public成員方法,包括繼承的
- Method[] getDeclaredMethods?():獲取所有成員方法,不包括繼承的
- Method getMethod?(String name, Class<?>... parameterTypes) :獲取單個(gè)public成員方法
- Method getDeclaredMethod?(String name, Class<?>... parameterTypes):獲取單個(gè)成員方法
- Method類中用于調(diào)用成員方法的方法Object invoke?(Object obj, Object... args):調(diào)用obj對象的成員方法,參數(shù)是args,返回值是Object類型
3.4反射獲取構(gòu)造、成員變量、成員方法Demo
學(xué)生類
class Student { private String name; public Integer age; public Student(){ } public Student(String name, Integer age){ this.name = name; this.age = age; } private String getUserType(String str) { System.out.println(str); return "學(xué)生-" + str; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
獲取構(gòu)造方法Demo
獲取無參構(gòu)造方法
Class aClass = Student.class; Constructor constructor = aClass.getConstructor(); Student newInstance = (Student)constructor.newInstance();
根據(jù)參數(shù)類型獲取有參構(gòu)造方法
// 根據(jù)參數(shù)類型獲取構(gòu)造方法 Class aClass = Student.class; Class<?>[] classes = {Class.forName("java.lang.String"), Class.forName("java.lang.Integer")}; Constructor c = aClass.getDeclaredConstructor(classes); Student student = (Student)c.newInstance("王明", 1); System.out.println(student.toString());
獲取成員變量方法
獲取所有成員變量方法
Class aClass = Student.class; Field[] fields = aClass.getDeclaredFields(); for (Field field : fields) { System.out.println(field.getName()); }
獲取指定成員變量方法
Class aClass = Student.class; Field name = aClass.getDeclaredField("name");
給private、public成員變量賦值
// 獲取name私有成員變量 Field name = aClass.getDeclaredField("name"); name.setAccessible(true); // 獲取age成員變量 Field age = aClass.getDeclaredField("age"); // 通過反射實(shí)例化對象 Student student = aClass.getConstructor().newInstance(); // 成員變量參數(shù)賦值 name.set(student, "王明"); age.set(student, 20); System.out.println(student.toString());
獲取成員方法
獲取本類中所有成員方法
Class aClass = Student.class; Method[] methods = aClass.getDeclaredMethods(); for (Method method : methods) { System.out.println(method.getName()); }
調(diào)用成員方法
// 獲取私有成員方法 Method getUserType = aClass.getDeclaredMethod("getUserType", Class.forName("java.lang.String")); // 關(guān)閉權(quán)限檢查 getUserType.setAccessible(true); // 實(shí)例化對象 Student student = aClass.getConstructor().newInstance(); // 調(diào)用方法,傳入?yún)?shù) Object invoke = getUserType.invoke(student, "王亮"); System.out.println(invoke);
到此這篇關(guān)于java反射常用方法的文章就介紹到這了,更多相關(guān)java反射常用方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java實(shí)現(xiàn)二維數(shù)組轉(zhuǎn)置的方法示例
這篇文章主要介紹了java實(shí)現(xiàn)二維數(shù)組轉(zhuǎn)置的方法,結(jié)合實(shí)例形式詳細(xì)分析了java二維數(shù)組轉(zhuǎn)置的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-10-10JavaSE反射、枚舉、lambda表達(dá)式常用方法舉例
這篇文章主要介紹了JavaSE反射、枚舉、lambda表達(dá)式常用方法的相關(guān)資料,反射允許在運(yùn)行時(shí)檢查和操作類、方法和屬性,枚舉提供了一種更安全和優(yōu)雅的方式來定義常量,而Lambda表達(dá)式則簡化了函數(shù)式接口的實(shí)現(xiàn),需要的朋友可以參考下2024-12-12springboot的SpringPropertyAction事務(wù)屬性源碼解讀
這篇文章主要介紹了springboot的SpringPropertyAction事務(wù)屬性源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11里氏代換原則_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要為大家詳細(xì)介紹了里氏代換原則的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08詳解JAVA 線程-線程的狀態(tài)有哪些?它是如何工作的?
這篇文章主要介紹了詳解JAVA 線程的的相關(guān)資料,文中講解非常細(xì)致,源碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以參考下2020-06-06SpringMVC?RESTFul實(shí)戰(zhàn)案例刪除功能實(shí)現(xiàn)
這篇文章主要為大家介紹了SpringMVC?RESTFul實(shí)戰(zhàn)案例刪除功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Spring 中如何根據(jù)環(huán)境切換配置 @Profile
這篇文章主要介紹了Spring中如何根據(jù)環(huán)境切換配置@Profile的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08