三. 重識Java之夯實反射

不忘初心 砥礪前行, Tomorrow Is Another Day !java

相關文章

引言

本文概要:數組

  1. 類的生命週期
  2. 基本類周邊信息的獲取
  3. 泛型類周邊信息的獲取
  4. 類內部信息獲取

一. 類的生命週期

  1. 編譯:生成Class相關文件
  2. 運行
    • 裝載 - 連接 - 初始化
  • 裝載: 類的裝載是經過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的方法區,而且在堆區建立描述這個類的java.lang.Class對象。用來封裝數據。 可是同一個類只會被類裝載器裝載一次,重要的話:類只裝載一次
  • 連接: 連接就是把二進制數據組裝爲能夠運行的狀態。連接分爲校驗,準備,解析這3個階段。校驗通常用來確認此二進制文件是否適合當前的JVM(版本),準備就是爲靜態成員分配內存空間,並設置默認值。解析指的是轉換常量池中的代碼做爲直接引用的過程,直到全部的符號引用均可以被運行程序使用(創建完整的對應關係)。
  • 初始化:初始化就是對類中的變量進行初始化值;完成以後,類型也就完成了初始化,初始化以後類的對象就能夠正常使用了,直到一個對象再也不使用以後,將被垃圾回收。釋放空間。 當沒有任何引用指向Class對象時就會被卸載,結束類的生命週期。若是再次用到就再從新開始裝載、連接和初始化的過程。

以上內容摘抄自 blog.csdn.net/harvic88092…bash

對於上述一大段理論,咱們就記住最重要標黑部分.下面開始來學習反射.函數

獲取類類型

使用示例post

/**
     * 獲取類類型的四種方式
     */
   private void getClassObjectMethod() throws ClassNotFoundException {
       Person person = new Person();
       Class<?> clazz1 = Person.class;
       Class<?> clazz2 = person.getClass();
       Class<?> clazz3 = Class.forName("reflectionDemo.bean.Person");
       Class<?> clazz4 = getClass().getClassLoader().loadClass("reflectionDemo.bean.Person");
       boolean result = (clazz1 == clazz2 && clazz3 == clazz4 && clazz1 == clazz3);
       System.out.println(result);
    }
複製代碼

Class.forName與ClassLoader.loadClass區別學習

  • Class.forName(String className)不只會將類加載進來,並且會對其進行初始化,而ClassLoader.loadClass(String ClassName)則只是將類加載進來,而沒有對類進行初始化
  • 通常來說,他們兩個是通用的,但若是你加載類依賴初始化值的話,那ClassLoader.loadClass(String ClassName)將再也不適用!

二. 基本類周邊信息的獲取相關API

//獲取類類型對象的幾種方式:
Person person = new Person();  
Class a = person.getClass() //方法一
Class b = Persion.class;//方法二
Class c = Class.forName(String ClassName); //方法三
Class d = context.getClassLoader().loadClass(String ClassName);//方法四:(不建議使用)
 
//獲取包名類名
public String getName();//獲取完整的類名(包含包名)
public String getSimpleName();//僅獲取類名
public Package getPackage()//獲取類類型所對應的package對象
 
//獲取超類Class對象
public Class<?> getSuperclass();//獲取普通父類Class對象(不越級,僅直接繼承的類)
public Type getGenericSuperclass();//獲取泛型父類Type對象(見下篇)
 
//獲取接口Class對象
public Class<?>[] getInterfaces();//獲取普通接口的Class對象(不越級,僅直接實現的直接)
public Type[] getGenericInterfaces();//獲取泛型接口的Type(見下篇)
 
//類訪問修飾符
int modifiers = clazz.getModifiers();//獲取類訪問修飾符對應的int變量
String Modifier.toString(int modifiers) //根據整型變量來生成對應的修飾符字符串
boolean Modifier.isAbstract(int modifiers)//isXXX()系列函數用以檢查特定的修飾符是否存在
複製代碼



三. 泛型類周邊信息的獲取相關API

瞭解泛型類周邊信息獲取,須要先了解下Type相關的知識.接下來看Type.ui

//獲取泛型超類的Type
public Type getGenericSuperclass();
//獲取泛型接口的Type
public Type[] getGenericInterfaces();

複製代碼

3.1 Type

Type的派生類:spa

  • Class
  • ParameterizedType,表明的是泛型類型形式的
  • TypeVariable,表明的是泛型變量形式的
  • GenericArrayType,表明的是數組形式的
    • 強調第一次:若是type對應的是表達式是ArrayList這種的,這個type類型應該是ParameterizedType,而不是GenericArrayType,只有相似Integer[]這種的纔是GenericArrayType類型。
  • WildcardType,表明的是通配符形式的
  • 小結.
    1. 當Type值表明的是完整的泛型表達式,好比:Point<...>,那它對應的類型就是ParameterizedType.
    2. 當Type值表明的是一個肯定的類,好比:Integer,String,Double等,那它所對應的類型就是Class;
    3. 當Type值表明的僅僅是Point中用來填充泛型變量T(暫未填充值時),那它所對應的類型就是TypeVariable.
    4. 當Type值表明的是一個String[]、Interge[]等數組時,那它對應的類型就是GenericArrayType.
    5. 當type所表明的是一個是通配符相關的表達式時?,那它對應的類型就是WildcardType.
3.1.1 ParameterizedType相關API
//獲取填充泛型變量的真實參數列表
Type[] getActualTypeArguments();
//獲取聲明此當前泛型表達式的類或接口的Class對象
Type getRawType();

複製代碼

繼承Type接口只有下面五個:.net

  • Class
  • ParameterizedType
  • TypeVariable
  • WildcardType
  • GenericArrayType
    因此這也是Type[ ] getActualTypeArguments()方法中Type[]數組的全部可能取值.
3.1.2 TypeVariable相關
//就是獲得當前泛型變量的名稱;
String  getName();
//返回表示此類型變量上邊界的 Type 對象的數組。若是沒有上邊界,則默認返回Object;
//上邊界的意思就是extends關鍵字後面的限定條件。
Type[]  getBounds();

複製代碼
3.1.3 GenericArrayType相關

強調第二次,若是type值對應的是相似於ArrayList、List這樣的類型,那type的類型應該是ParameterizedType,而不是GenericArrayType,因此當且僅當type對應的類型是相似於String[]、Integer[]這樣的數組時,type的類型纔是GenericArrayTypecode

//獲取實際數組值所對應的Type,通常獲取到後進行強制轉換成Class
Type getGenericComponentType();

複製代碼
3.1.4 WildcardType相關

當type所表明的表達式是類型通配符相關的表達式時,好比,,或者等,這個type的類型就是WildcardType!

//獲取通配符的上邊界對象列表
//上邊界就是使用extends關鍵定所作的的限定,若是沒有默認是Object
Type[] getUpperBounds();
//獲取通配符的下邊界對象列表
//下邊界是指使用super關鍵字所作的限定,若是沒有,則爲Null
Type[] getLowerBounds();

複製代碼
3.1.4.1 通配符的使用範圍

再次重複一次有關通配符的知識,具體見[夯實泛型]

  • 通配符只是泛型變量的填充類型的一種,不能作爲泛型變量使用
  • 通配符只能用來在生成泛型實例時使用,如Box<?> box;中,其它位置都是不對的.
3.1.4.2 通用類型轉換函數
private void parseClass(Class<?> c){
    parseTypeParameters(c.getGenericInterfaces());
}

private void parseTypeParameters(Type[] types){
    for(Type type:types){
        parseTypeParameter(type);
    }
}

private void parseTypeParameter(Type type){
    if(type instanceof Class){
        Class<?> c = (Class<?>) type;
        Log.d(TAG, c.getSimpleName());
    } else if(type instanceof TypeVariable){
        TypeVariable<?> tv = (TypeVariable<?>)type;
        Log.d(TAG, tv.getName());
        parseTypeParameters(tv.getBounds());
    } else if(type instanceof WildcardType){
        WildcardType wt = (WildcardType)type;
        Log.d(TAG, "?");
        parseTypeParameters(wt.getUpperBounds());
        parseTypeParameters(wt.getLowerBounds());
    } else if(type instanceof ParameterizedType){
        ParameterizedType pt = (ParameterizedType)type;
        Type t = pt.getOwnerType();
        if(t != null) {
            parseTypeParameter(t);
        }
        parseTypeParameter(pt.getRawType());
        parseTypeParameters(pt.getActualTypeArguments());
    } else if (type instanceof GenericArrayType){
        GenericArrayType arrayType = (GenericArrayType)type;
        Type t = arrayType.getGenericComponentType();
        parseTypeParameter(t);
    }
複製代碼



四. 類內部信息獲取

4.1 獲取構造函數Constructor相關API

void setAccessible(boolean flag),它表明的含義是,是否將任何函數或字段設置爲可訪問的。若是設置爲true,就無論這個函數或者字段是聲明爲private仍是public,都是能夠訪問的,默認狀況下是false,即只有public類型是可訪問的

/**
* 1. 獲取構造函數Constructor
*/
//獲取public類型的構造函數
Constructor<?>[] getConstructors();
Constructor<T> getConstructor(Class<?>... parameterTypes);//根據參數類型,獲取指定的構造的構造函數,屬於精確匹配,參數聲明順序、類型及個數要徹底匹配.
//獲取全部類型的構造函數
Constructor<?>[] getDeclaredConstructors();
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)//同上
 
/*
* 2. Constructor之獲取對應類的實例
× @params args 傳入的參數類型、順序及個數都必須與當前的Constructor對象一一對應
*/
public T newInstance(Object... args);
 
/**
* 3. Constructor之獲取參數類型
*/
//用於解析通常函數
Class<?>[] getParameterTypes();
//用於解析泛型對象
Type[] getGenericParameterTypes();
 
 
/***公有的***/ 
// Constructor之獲取訪問修飾符
int getModifiers()
//獲取聲明Constructor的類Class對象;
Class<T> getDeclaringClass()
複製代碼
4.2 獲取成員變量Field相關API
/**
* 1. 獲取Field對象
*/
//獲取public類型的成員變量
Field[] getFields();
Field getField(String name);//根據變量名,獲取對應的Field對象
//獲取全部類型的成員變量
Field[] getDeclaredFields();
Field getDeclaredField(String name)//同上
 
/**
* 2. get,set方法系列
* 當獲取或設置指定類對象中某變量的值
*/
//object:要設置的類對象(類實例),value:是此Field對象所對應的值
void set(Object object, Object value)
//object:要獲取值的類的對象,返回值Object爲:在此類的實例中,對應成員變量的值
Object get(Object object)

/**
 × 3. 針對基本數據類型
 ×/
//設置與獲取int類型的值
void setInt(Object object, int value)
int getInt(Object object)
//設置與獲取double類型的值
void setDouble(Object object, double value)
double getDouble(Object object)
//設置與獲取float類型的值
void setFloat(Object object, float value)
float getFloat(Object object)
//設置與獲取bool類型的值
void setBoolean(Object object, boolean value)
boolean getBoolean(Object object)
//設置與獲取short類型的值
void setShort(Object object, short value)
short getShort(Object object)
//設置與獲取long類型的值
void setLong(Object object, long value)
long getLong(Object object)
//設置與獲取byte類型的值
void setByte(Object object, byte value)
byte getByte(Object object)
//設置與獲取char類型的值
void setChar(Object object, char value)
char getChar(Object object)
 
/**
* 4. 判斷當前field是否爲枚舉常量;
*/
boolean isEnumConstant()

/***公有的***/
//獲取訪問修飾符
int getModifiers()
//獲取聲明該Field的類class對象
Class<?> getDeclaringClass()
複製代碼
4.3 獲取成員方法相關API
/*
* 1. 獲取指定類中的成員函數Method對象
*/
//獲取public的成員函數
Method[] getMethods()
Method getMethod(String name, Class<?>... parameterTypes)//name爲方法名,parameterTypes爲參數類型,精確匹配
//獲取全部類型成員函數
Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, Class<?>... parameterTypes)//同上

/*
* 2. 執行某個方法
× @params receicer: 指要執行該函數的類對象(類實例),好比咱們的Person類的某一實例
* @params args: 用於傳入該函數聲明中的參數所對應的值的列表
* @return Object: 將函數的結果返回,Object對象就是執行此函數後返回的結果
*/
Object invoke(Object receiver, Object... args)
 
/**
* 3. 獲取參數類型
*/
Class<?>[] getParameterTypes()
Type[] getGenericParameterTypes()
 
/**
* 4. 獲取返回值類型
*/
Class<?> getReturnType()
Type getGenericReturnType()

複製代碼

因爲本人技術有限,若有錯誤的地方,麻煩你們給我提出來,本人不勝感激,你們一塊兒學習進步.

爲方便往後查找,本文只記載了重難點知識API使用,如需詳細瞭解學習.敬請參考,這裏感謝原做者啓艦的博客對本人的幫助.

相關文章
相關標籤/搜索