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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

反射获取list泛型_Android 从浅到懂使用反射机制

發布時間:2023/12/3 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反射获取list泛型_Android 从浅到懂使用反射机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

定義

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

使用場景

反射是在運行時獲取確定類型,綁定對象。

常見的兩個使用場景

  • 運行時獲取對象的所有信息
  • 泛型擦除
  • 在運行時獲取類

    這里的運行時指的是程序在運行后。相應的還有編譯時,編譯時是編譯器將源代碼翻譯成機器能識別的代碼。

    舉個例子說明編譯時和運行時的區別:

    泛型擦除

    示例:設定集合是Int,但是最后輸出的集合中包含String,這就實現了泛型擦除功能。

    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]

    反射的利弊

    • 運行時類型的判斷
    • 動態類加載,動態代理使用反射。

    • 性能問題,反射相當于一系列解釋操作。
    • JVM 不會去優化這部分代碼
    • 代碼不易閱讀

    為什么會出現性能問題?

  • Method#invoke 方法會對參數做封裝和解封操作
  • 需要檢查方法可見性
  • 需要校驗參數
  • 反射方法難以內聯
  • JVM 無法優化: Java 文檔中介紹
  • 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.?檢查方法權限
    ????????????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.?檢查方法權限
    ????????????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);
    ????}
    }

    如何使用

    想要使用反射機制,就必須要先獲取到該類的字節碼文件對象(.class),通過字節碼文件對象,就能夠通過該類中的方法獲取到我們想要的所有信息(方法,屬性,類名,父類名,實現的所有接口等等),每一個類對應著一個字節碼文件也就對應著一個Class類型的對象。

    獲取字節碼文件對象

    • 1、根據類名:類名.class
    • 2、根據對象:對象.getClass()
    • 3、根據全限定類名:Class.forName(全限定類名)

    常用的是第一種。

    獲取構造函數

    構造函數分為兩種:帶參和不帶參

    • 獲取不帶參構造函數
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getDeclaredConstructor();
    Object?user?=?constructor.newInstance();
    • 獲取帶參構造函數
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor(int.class,String.class);
    Object?user?=?constructor.newInstance(1,"張三");

    獲取成員變量

    成員變量一般為公有和私有

    • 獲取公有成員變量
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=?constructor.newInstance();
    Field?declaredField?=?classs.getField("userName");
    //?賦新值
    declaredField.set(user,?"李四");
    • 獲取私有成員變量
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=?constructor.newInstance();
    Field?declaredField?=?classs.getDeclaredField("userName");
    //?因為屬性是私有的,所有需要打開可見權限
    declaredField.setAccessible(true);
    //?賦新值
    declaredField.set(user,?"李四");

    獲取方法

    成員方法一般為公有和私有,同時方法也分有參和無參

    • 獲取公有成員無參方法
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=?constructor.newInstance();
    Method?method?=?classs.getMethod("getUserName");
    method.invoke(user);
    • 獲取公有成員有參方法
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=?constructor.newInstance();
    Method?method?=?classs.getMethod("getUserName",?String.class);
    method.invoke(user,?"王五");
    • 獲取私有成員無參方法
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=?constructor.newInstance();
    Method?method?=?classs.getDeclaredMethod("getUserName");
    //?因為屬性是私有的,所有需要打開可見權限
    method.setAccessible(true);
    method.invoke(user);
    • 獲取私有成員有參方法
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getConstructor();
    Object?user?=??constructor.newInstance();
    Method?method?=?classs.getDeclaredMethod("getUserName",String.class);
    //?因為屬性是私有的,所有需要打開可見權限
    method.setAccessible(true);
    method.invoke(user,?"王五");

    Tip

  • 一般來說,構造函數大部分是 public ,而成員變量和方法大部分是private。public 權限直接正常調用即可、private需要在調用前增加 setAccessible(true)
  • 獲取構造函數、成員變量、成員方法都有一個獲取所有的方法,根據需要去調用。如:getConstructor:獲取單個構造函數,getConstructors:獲取所有構造函數
  • 總結

    反射的作用是在運行時動態獲取對象信息。

    實現步驟:

  • 獲取 Class:有三種方式,常用的是 Class.forName("類全名稱")
  • 獲取構造函數:通過 Class 對象調用 如:clz.getConstructor() 得到構造函數
  • 創建對象:通過構造函數創建對象 如:con.newInstance()
  • 沒有 Declared 前綴會返回所有的 public 方法,包括父類的方法。而加 Declared 前綴會返回所有自己定義的方法,public,protected,private 都在此,但是不包括父類的方法。

    這也正是 getMethod 和 getDeclaredMethod 的區別。

    • 獲取私有構造函數
    Class?classs?=?Class.forName("com.xxx.xxx.User");
    Constructor?constructor?=?classs.getDeclaredConstructor();
    //?因為屬性是私有的,所有需要打開可見權限
    constructor.setAccessible(true);
    Object?user?=?constructor.newInstance();

    • 獲取私有成員變量
    ...
    Field?declaredField?=?classs.getDeclaredField("userName");
    //?因為屬性是私有的,所有需要打開可見權限
    declaredField.setAccessible(true);

    • 獲取私有成員方法
    ...
    Method?method?=?classs.getDeclaredMethod("getUserName");
    //?因為屬性是私有的,所有需要打開可見權限
    method.setAccessible(true);

    反射耗時的原因:

    • invoke方法需要做封裝和解封操作
    • 需要類型檢查、權限檢查
    • 需要校驗參數
    • 需要檢查方法的可見性
    • JVM無法做優化

    參考

    • Reflection:Java反射機制的應用場景
    • 深入淺出Java反射原理和使用場景
    • java反射機制詳解
    • Java 反射 -超詳細講解(附源碼)
    • java反射為什么慢
    • 強大的反射庫 FreeReflection
    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的反射获取list泛型_Android 从浅到懂使用反射机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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