Java無所不能的反射在Android中須要熟練的知識

什麼是反射?

反射 (Reflection) 是 Java 的特徵之一,它容許運行中的 Java 程序獲取自身的信息,而且能夠操做類或對象的內部屬性 簡而言之,經過反射,咱們能夠在運行時得到程序或程序集中每個類型的成員和成員的信息。程序中通常的對象的類型都是在編譯期就肯定下來的,而 Java 反射機制能夠動態地建立對象並調用其屬性,這樣的對象的類型在編譯期是未知的。因此咱們能夠經過反射機制直接建立對象,即便這個對象的類型在編譯期是未知的。 反射的核心是 JVM 在運行時才動態加載類或調用方法/訪問屬性,它不須要事先(寫代碼的時候或編譯期)知道運行對象是誰。 Java 反射主要提供如下功能:java

  • 在運行時判斷任意一個對象所屬的類;
  • 在運行時構造任意一個類的對象;
  • 在運行時判斷任意一個類所具備的成員變量和方法(經過反射甚至能夠調用private方法);
  • 在運行時調用任意一個對象的方法 重點:是運行時而不是編譯時

反射的運用

得到 Class 對象

  • 使用 Class 類的 forName 靜態方法
public static Class<?> forName(String className)
複製代碼
  • 直接獲取某一個對象的 class
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;
複製代碼
  • 調用某個對象的 getClass() 方法
StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();
複製代碼

判斷是否爲某個類的實例

通常地,咱們用 instanceof 關鍵字來判斷是否爲某個類的實例。同時咱們也能夠藉助反射中 Class 對象的 isInstance() 方法來判斷是否爲某個類的實例,它是一個 native 方法:面試

public native boolean isInstance(Object obj);
複製代碼

建立實例

經過反射來生成對象主要有兩種方式。數組

  • 使用Class對象的newInstance()方法來建立Class對象對應類的實例。
Class<?> c = String.class;
Object str = c.newInstance();
複製代碼
  • 先經過Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來建立實例。這種方法能夠用指定的構造器構造類的實例。
//獲取String所對應的Class對象
Class<?> c = String.class;
//獲取String類帶一個String參數的構造器
Constructor constructor = c.getConstructor(String.class);
//根據構造器建立實例
Object obj = constructor.newInstance("23333");
System.out.println(obj);
複製代碼

獲取構造器信息

獲得構造器的方法安全

Constructor getConstructor(Class[] params) -- 得到使用特殊的參數類型的公共構造函數, 
Constructor[] getConstructors() -- 得到類的全部公共構造函數 
Constructor getDeclaredConstructor(Class[] params) -- 得到使用特定參數類型的構造函數(與接入級別無關) 
Constructor[] getDeclaredConstructors() -- 得到類的全部構造函數(與接入級別無關)
複製代碼

獲取類構造器的用法與上述獲取方法的用法相似。主要是經過Class類的getConstructor方法獲得Constructor類的一個實例,而Constructor類有一個newInstance方法能夠建立一個對象實例:bash

public T newInstance(Object ... initargs)
複製代碼

獲取類的成員變量(字段)信息

得到字段信息的方法微信

Field getField(String name) -- 得到命名的公共字段 
Field[] getFields() -- 得到類的全部公共字段 
Field getDeclaredField(String name) -- 得到類聲明的命名的字段 
Field[] getDeclaredFields() -- 得到類聲明的全部字段 
複製代碼

調用方法

得到方法信息的方法架構

Method getMethod(String name, Class[] params) -- 使用特定的參數類型,得到命名的公共方法 
Method[] getMethods() -- 得到類的全部公共方法 
Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的參數類型,得到類聲明的命名的方法 
Method[] getDeclaredMethods() -- 得到類聲明的全部方法 
複製代碼

當咱們從類中獲取了一個方法後,咱們就能夠用 invoke() 方法來調用這個方法。invoke 方法的原型爲:函數

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
複製代碼

利用反射建立數組

數組在Java裏是比較特殊的一種類型,它能夠賦值給一個Object Reference 其中的Array類爲java.lang.reflect.Array類。咱們經過Array.newInstance()建立數組對象,它的原型是:ui

public static Object newInstance(Class<?> componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }
複製代碼

newArray 方法是一個 native 方法,它在 HotSpot JVM 裏的具體實現咱們後邊再研究,這裏先把源碼貼出來:spa

private static native Object newArray(Class<?> componentType, int length)
        throws NegativeArraySizeException;
複製代碼

注意事項

  • 反射會額外消耗必定的系統資源,所以若是不須要動態地建立一個對象,那麼就不須要用反射
  • 反射調用方法時能夠忽略權限檢查,所以可能會破壞封裝性而致使安全問題

最後

讀到這的朋友以爲不錯能夠點贊關注下,感謝您的支持,之後會不停更新更多精選乾貨及資訊分享,歡迎你們在評論區留言討論!

歡迎關注享學課堂online微信公衆號,天天會持續更新技術乾貨,熱點,吐槽等文章,還有免費的Android架構視頻資料和麪試專題資料免費領取分享,後臺回覆關鍵字【Android資料】,免費獲取Android架構面試專題文檔資料、電子書及更多架構進階視頻資料(視頻+筆記)

相關文章
相關標籤/搜索