反射获取list泛型_Android 从浅到懂使用反射机制
定義
Java 反射機(jī)制是發(fā)生在運(yùn)行狀態(tài)中,對于任何一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任何一個(gè)對象,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為 Java 語言的反射機(jī)制。
使用場景
反射是在運(yùn)行時(shí)獲取確定類型,綁定對象。
常見的兩個(gè)使用場景
在運(yùn)行時(shí)獲取類
這里的運(yùn)行時(shí)指的是程序在運(yùn)行后。相應(yīng)的還有編譯時(shí),編譯時(shí)是編譯器將源代碼翻譯成機(jī)器能識別的代碼。
舉個(gè)例子說明編譯時(shí)和運(yùn)行時(shí)的區(qū)別:
泛型擦除
示例:設(shè)定集合是Int,但是最后輸出的集合中包含String,這就實(shí)現(xiàn)了泛型擦除功能。
val?list?=?arrayListOf(1,2,3)val?clz?=?Class.forName("java.util.ArrayList")
val?method?=?clz.getMethod("add",?Object::class.java)method.invoke(list,"hhh")Log.e(TAG,"list:${list.toString()}")
輸出:
list:[1,?2,?3,?hhh]
反射的利弊
利
- 運(yùn)行時(shí)類型的判斷
- 動態(tài)類加載,動態(tài)代理使用反射。
弊
- 性能問題,反射相當(dāng)于一系列解釋操作。
- JVM 不會去優(yōu)化這部分代碼
- 代碼不易閱讀
為什么會出現(xiàn)性能問題?
invoke方法源碼:
class?Class?{????@CallerSensitive
????public?Method?getMethod(String?name,?Class>...?parameterTypes)throws?NoSuchMethodException,?SecurityException?{
????????Objects.requireNonNull(name);
????????SecurityManager?sm?=?System.getSecurityManager();
????????if?(sm?!=?null)?{
????????????//?1.?檢查方法權(quán)限
????????????checkMemberAccess(sm,?Member.PUBLIC,?Reflection.getCallerClass(),?true);
????????}
????????//?2.?獲取方法
????????Method?method?=?getMethod0(name,?parameterTypes);
????????if?(method?==?null)?{
????????????throw?new?NoSuchMethodException(methodToString(name,?parameterTypes));
????????}
????????//?3.?返回方法的拷貝
????????return?getReflectionFactory().copyMethod(method);
????}
????@CallerSensitive
????public?Method?getDeclaredMethod(String?name,?Class>...?parameterTypes)throws?NoSuchMethodException,?SecurityException?{
????????Objects.requireNonNull(name);
????????SecurityManager?sm?=?System.getSecurityManager();
????????if?(sm?!=?null)?{
????????????//?1.?檢查方法權(quán)限
????????????checkMemberAccess(sm,?Member.DECLARED,?Reflection.getCallerClass(),?true);
????????}
????????//?2.?獲取方法
????????Method?method?=?searchMethods(privateGetDeclaredMethods(false),?name,?parameterTypes);
????????if?(method?==?null)?{
????????????throw?new?NoSuchMethodException(methodToString(name,?parameterTypes));
????????}
????????//?3.?返回方法的拷貝
????????return?getReflectionFactory().copyMethod(method);
????}
}
如何使用
想要使用反射機(jī)制,就必須要先獲取到該類的字節(jié)碼文件對象(.class),通過字節(jié)碼文件對象,就能夠通過該類中的方法獲取到我們想要的所有信息(方法,屬性,類名,父類名,實(shí)現(xiàn)的所有接口等等),每一個(gè)類對應(yīng)著一個(gè)字節(jié)碼文件也就對應(yīng)著一個(gè)Class類型的對象。
獲取字節(jié)碼文件對象
- 1、根據(jù)類名:類名.class
- 2、根據(jù)對象:對象.getClass()
- 3、根據(jù)全限定類名:Class.forName(全限定類名)
常用的是第一種。
獲取構(gòu)造函數(shù)
構(gòu)造函數(shù)分為兩種:帶參和不帶參
- 獲取不帶參構(gòu)造函數(shù)
Constructor?constructor?=?classs.getDeclaredConstructor();
Object?user?=?constructor.newInstance();
- 獲取帶參構(gòu)造函數(shù)
Constructor?constructor?=?classs.getConstructor(int.class,String.class);
Object?user?=?constructor.newInstance(1,"張三");
獲取成員變量
成員變量一般為公有和私有
- 獲取公有成員變量
Constructor?constructor?=?classs.getConstructor();
Object?user?=?constructor.newInstance();
Field?declaredField?=?classs.getField("userName");
//?賦新值
declaredField.set(user,?"李四");
- 獲取私有成員變量
Constructor?constructor?=?classs.getConstructor();
Object?user?=?constructor.newInstance();
Field?declaredField?=?classs.getDeclaredField("userName");
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
declaredField.setAccessible(true);
//?賦新值
declaredField.set(user,?"李四");
獲取方法
成員方法一般為公有和私有,同時(shí)方法也分有參和無參
- 獲取公有成員無參方法
Constructor?constructor?=?classs.getConstructor();
Object?user?=?constructor.newInstance();
Method?method?=?classs.getMethod("getUserName");
method.invoke(user);
- 獲取公有成員有參方法
Constructor?constructor?=?classs.getConstructor();
Object?user?=?constructor.newInstance();
Method?method?=?classs.getMethod("getUserName",?String.class);
method.invoke(user,?"王五");
- 獲取私有成員無參方法
Constructor?constructor?=?classs.getConstructor();
Object?user?=?constructor.newInstance();
Method?method?=?classs.getDeclaredMethod("getUserName");
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
method.setAccessible(true);
method.invoke(user);
- 獲取私有成員有參方法
Constructor?constructor?=?classs.getConstructor();
Object?user?=??constructor.newInstance();
Method?method?=?classs.getDeclaredMethod("getUserName",String.class);
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
method.setAccessible(true);
method.invoke(user,?"王五");
Tip
總結(jié)
反射的作用是在運(yùn)行時(shí)動態(tài)獲取對象信息。
實(shí)現(xiàn)步驟:
沒有 Declared 前綴會返回所有的 public 方法,包括父類的方法。而加 Declared 前綴會返回所有自己定義的方法,public,protected,private 都在此,但是不包括父類的方法。
這也正是 getMethod 和 getDeclaredMethod 的區(qū)別。
- 獲取私有構(gòu)造函數(shù)
Constructor?constructor?=?classs.getDeclaredConstructor();
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
constructor.setAccessible(true);
Object?user?=?constructor.newInstance();
- 獲取私有成員變量
Field?declaredField?=?classs.getDeclaredField("userName");
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
declaredField.setAccessible(true);
- 獲取私有成員方法
Method?method?=?classs.getDeclaredMethod("getUserName");
//?因?yàn)閷傩允撬接械?#xff0c;所有需要打開可見權(quán)限
method.setAccessible(true);
反射耗時(shí)的原因:
- invoke方法需要做封裝和解封操作
- 需要類型檢查、權(quán)限檢查
- 需要校驗(yàn)參數(shù)
- 需要檢查方法的可見性
- JVM無法做優(yōu)化
參考
- Reflection:Java反射機(jī)制的應(yīng)用場景
- 深入淺出Java反射原理和使用場景
- java反射機(jī)制詳解
- Java 反射 -超詳細(xì)講解(附源碼)
- java反射為什么慢
- 強(qiáng)大的反射庫 FreeReflection
總結(jié)
以上是生活随笔為你收集整理的反射获取list泛型_Android 从浅到懂使用反射机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吉普寨是哪里的国家 吉普寨属于哪里的国家
- 下一篇: toastutils报错_史上最好用的A