Java語法進階15-反射

反射

類加載

類在內存中的生命週期:加載-->使用-->卸載java

當程序主動使用某個類時,若是該類還未被加載到內存中,系統會經過加載、鏈接、初始化三個步驟來對該類進行初始化程序員

類的加載又分爲三個階段:數組

(1)加載:loadui

就是指將類型的class字節碼數據讀入內存編碼

(2)鏈接:linkspa

  ①驗證:校驗合法性等code

  ②準備:準備對應的內存(方法區),建立Class對象,爲類變量賦默認值,爲靜態常量賦初始值。component

  ③解析:把字節碼中的符號引用替換爲對應的直接地址引用對象

(3)初始化:initialize(類初始化)即執行<clinit>類初始化方法,大多數狀況下,類的加載就完成了類的初始化,有些狀況下,會延遲類的初始化。blog

類初始化

一、哪些操做會致使類的初始化?

(1)運行主方法所在的類,要先完成類初始化,再執行main方法

(2)第一次使用某個類型就是在new它的對象,此時這個類沒有初始化的話,先完成類初始化再作實例初始化

(3)調用某個類的靜態成員(類變量和類方法),此時這個類沒有初始化的話,先完成類初始化

(4)子類初始化時,發現它的父類尚未初始化的話,那麼先初始化父類

(5)經過反射操做某個類時,若是這個類沒有初始化,也會致使該類先初始化

二、哪些使用類的操做,可是不會致使類的初始化?

(1)使用某個類的靜態的常量(static final)

(2)經過子類調用父類的靜態變量,靜態方法,只會致使父類初始化,不會致使子類初始化。

(3)用某個類型聲明數組並建立數組對象時,不會致使這個類初始化

類加載器

(1)引導類加載器(Bootstrap Classloader)又稱爲根類加載器

   它負責加載jre/rt.jar核心庫,它自己不是Java代碼實現的,也不是ClassLoader的子類,獲取它的對象時每每返回null

(2)擴展類加載器(Extension ClassLoader)

  它負責加載jre/lib/ext擴展庫,它是ClassLoader的子類

(3)應用程序類加載器(Application Classloader)

    它負責加載項目的classpath路徑下的類,它是ClassLoader的子類

(4)自定義類加載器

  當你的程序須要加載「特定」目錄下的類,能夠自定義類加載器;

加載器的雙親委託模式

 下一級的類加載器,若是接到任務時,會先搜索是否加載過,若是沒有,會先把任務往上傳,若是都沒有加載過,一直到根加載器,若是根加載器在它負責的路徑下沒有找到,會往回傳,若是一路回傳到最後一級都沒有找到,那麼會報ClassNotFoundException或NoClassDefError

 類加載器之間不是繼承關係,是組合的方式實現的。

Class

 Java反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;

簡單理解爲JVM運行時會在方法區記錄全部class文件中全部類的信息(類名,屬性,方法),並將全部類又作爲Class類的對象。當調用某個類時就會將其先加載到內存中,

也就是將這個類做爲Class類的對象被建立出來。在Class類中定義了許多供操做(此類)的方法(建立對象,調用屬性和方法),從而能夠動態的修改程序結構

Class對象是反射的根源,全部Java類型均可以獲取它的類型對象。

Class 類的對象是在加載類時由 Java 虛擬機以及經過調用類加載器中的 defineClass方法自動構造,在方法區建立的,不是由程序員建立的,Class 沒有公共構造方法。

獲取Class對象的四種方式

(1)類型名.class

要求編譯期間已知類型

(2)對象.getClass()

獲取對象的運行時類型

(3)Class.forName(類型全名稱)

能夠獲取編譯期間未知的類型

(4)ClassLoader的類加載器對象.loadClass(類型全名稱)

能夠用系統類加載對象或自定義加載器對象加載指定路徑下的類型

獲取類型的詳細信息

能夠獲取:包、修飾符、類型名、父類(包括泛型父類)、父接口(包括泛型父接口)、成員(屬性、構造器、方法)、註解(類上的、方法上的、屬性上的)

public ClassLoader getClassLoader() 【返回該類的類加載器】
public String toString() 【將對象轉換爲字符串】
public Package getPackage() 【獲取此類的包】
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一個 Constructor 對象,該對象反映此 Class 對象所表示的類或接口的指定構造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException 【返回此 Class 對象表示的類聲明的全部構造方法】
public native int getModifiers();

【 返回此類或接口以整數編碼的 Java 語言修飾符,用二進制的某一位1,來表明一種修飾符】

public String getName()

【以 String 的形式返回此 Class 對象所表示的實體(類、接口、數組類、基本類型或 void)名稱】

public native Class<? super T> getSuperclass();

【返回表示此 Class 所表示的實體(類、接口、基本類型或 void)的超類的 Class】

public Type getGenericSuperclass()

【返回此 Class 所表示的實體(類、接口、基本類型或 void)

直接超類的 Type】

public Class<?>[] getInterfaces() 【肯定此對象所表示的類或接口實現的接口】
public Field getField(String name) 【返回此 Class 對象所表示的類或接口的指定公共成員字段】
public Field[] getFields() throws SecurityException 【返回此 Class 對象所表示的類或接口的全部可訪問公共字段】
public Field getDeclaredField(String name) 【返回此 Class 對象所表示的類或接口的指定已聲明字段】
public Field[] getDeclaredFields() throws SecurityException 【返回此 Class 對象所表示的類或接口所聲明的全部字段】
public Method getMethod(String name, Class<?>... parameterTypes) 【返回此 Class 對象所表示的類或接口的指定公共成員方法】
public Method[] getMethods() throws SecurityException

【返回此 Class 對象所表示的類或接口(包括那些由該類或接口

聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法】

public Method getDeclaredMethod(String name, Class<?>... parameterTypes) 【返回此 Class 對象所表示的類或接口的指定已聲明方法】
public Method[] getDeclaredMethods() throws SecurityException

【此 Class 對象表示的類或接口聲明的全部方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法】

public T newInstance() 【建立此 Class 對象所表示的類的一個新實例】
public Annotation[] getAnnotations() 【返回此元素上存在的全部註釋】
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) 【若是存在該元素的指定類型的註釋,則返回這些註釋,不然返回 null】
public T[] getEnumConstants() 【若是此 Class 對象不表示枚舉類型,則返回枚舉類的元素或 null】
public boolean isMemberClass() 【當且僅當底層類是成員類時返回 true】
public native boolean isInterface(); 【斷定指定的 Class 對象是否表示一個接口類型】

建立任意引用類型的對象

一、直接經過Class對象來實例化(要求必須有無參構造)

  • (1)獲取該類型的Class對象(2)建立對象 newInstance()

二、經過獲取構造器對象來進行實例化

  • (1)獲取該類型的Class對象(2)獲取構造器對象(3)建立對象 newInstance(Object... initargs)

若是構造器的權限修飾符修飾的範圍不可見,也能夠調用setAccessible(true)

操做任意類型的屬性

(1)獲取該類型的Class對象

Class clazz = Class.forName("com.guigu.bean.User");

(2)獲取屬性對象

Field field = clazz.getDeclaredField("username");

(3)設置屬性可訪問

field.setAccessible(true);

(4)建立實例對象:若是操做的是非靜態屬性,須要建立實例對象

Object obj = clazz.newInstance();

(4)設置屬性值

field.set(obj,"chai");

(5)獲取屬性值 Object value = field.get(obj);

若是操做靜態屬性變量,那麼實例對象能夠省略,用null表示

調用任意類型的方法

(1)獲取該類型的Class對象

Class clazz = Class.forName("com.atguigu.service.UserService");

(2)獲取方法對象

Method method = clazz.getDeclaredMethod("login",String.class,String.class);

(3)建立實例對象

Object obj = clazz.newInstance();

(4)調用方法

Object result = method.invoke(obj,"chai","123);

若是方法的權限修飾符修飾的範圍不可見,也能夠調用setAccessible(true)

若是方法是靜態方法,實例對象也能夠省略,用null代替

獲取泛型父類

一、獲取子類的Class對象

二、調用getGenericSuperClass()獲取泛型父類

三、強轉爲ParameterizedType類型

四、調用getActualTypeArguments()獲取實際類型參數

讀取註解信息

獲取上的註解:

一、獲取Class對象

二、調用getAnnotation()方法獲得註解對象

三、調用註解對象的配置參數的方法獲取配置參數值

獲取屬性上的註解:

一、獲取Class對象

二、獲取某個屬性Field對象

三、調用getAnnot ation()方法獲得註解對象

四、調用註解對象的配置參數的方法獲取配置參數值

獲取方法上的註解:

一、獲取Class對象

二、獲取某個方法method對象

三、調用getAnnot ation()方法獲得註解對象

四、調用註解對象的配置參數的方法獲取配置參數值

獲取內部類或外部類信息

public Class<?>[] getClasses():  

【返回全部公共內部類和內部接口。包括從超類繼承的公共類和接口成員以及該類聲明的公共類和接口成員。】

public Class<?>[] getDeclaredClasses():

【返回 Class 對象的一個數組,這些對象反映聲明爲此 Class 對象所表示的類的成員的全部類和接口。包括該類所聲明的公共、保護、默認(包)訪問及私有類和接口,但不包括繼承的類和接口】 

public Class<?> getDeclaringClass(): 

【若是此 Class 對象所表示的類或接口是一個內部類或內部接口,則返回它的外部類或外部接口,不然返回null。】 

動態建立和操做任意類型的數組

java.lang.reflect包下還提供了一個Array類,Array對象能夠表明全部的數組。程序能夠經過使用Array類來動態的建立數組,操做數組元素等。

Array類提供了以下幾個方法:

public static Object newInstance(Class<?> componentType, int... dimensions):

【建立一個具備指定的組件類型和維度的新數組。】

public static void setXxx(Object array,int index,xxx value):

【將array數組中[index]元素的值修改成value。此處的Xxx對應8種基本數據類型,若是該屬性的類型是引用數據類型,則直接使用set(Object array,int index, Object value)方法。】

public static xxx getXxx(Object array,int index,xxx value):

【將array數組中[index]元素的值返回。此處的Xxx對應8種基本數據類型,若是該屬性的類型是引用數據類型,則直接使用get(Object array,int index)方法。】

Field

String getName() 返回此 Field 對象表示的字段的名稱
Object get(Object obj) 返回指定對象上此 Field 表示的字段的值
int getModifiers() 以整數形式返回由此 Field 對象表示的字段的 Java 語言修飾符
boolean equals(Object obj) 將此 Field 與指定對象比較
Type getGenericType() 返回一個 Type 對象,它表示此 Field 對象所表示字段的聲明類型
boolean getBoolean(Object obj) 獲取一個靜態或實例 boolean 字段的值
int getInt(Object obj) 獲取 int 類型或另外一個經過擴輾轉換能夠轉換爲 int 類型的基本類型的靜態或實例字段的值
void set(Object obj, Object value) 將指定對象變量上此 Field 對象表示的字段設置爲指定的新值
void setShort(Object obj, short s) 將字段的值設置爲指定對象上的一個 short 值
void setInt(Object obj, int i) 將字段的值設置爲指定對象上的一個 int 值

Method

boolean equals(Object obj) 將此 Method 與指定對象進行比較
String getName() 以 String 形式返回此 Method 對象表示的方法名稱
Object invoke(Object obj, Object... args) 對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法
Class<?> getReturnType() 返回一個 Class 對象,該對象描述了此 Method 對象所表示的方法的正式返回類型
Class<?>[] getParameterTypes() 按照聲明順序返回 Class 對象的數組,這些對象描述了此 Method 對象所表示的方法的形參類型
int getModifiers() 以整數形式返回此 Method 對象所表示方法的 Java 語言修飾符
Type getGenericReturnType() 返回表示由此 Method 對象所表示方法的正式返回類型的 Type 對象
Type[] getGenericParameterTypes() 返回一個 Type對象的數組, Type以聲明順序表示由該對象表示的可執行文件的形式參數類型
Type[] getGenericExceptionTypes() 返回一個 Type對象的數組, Type此可執行對象聲明拋出的異常
Class<?>[] getExceptionTypes() 返回 Class 對象的數組,這些對象描述了聲明將此 Method 對象表示的底層方法拋出的異常類型
Class<?> getDeclaringClass() 返回表示聲明由此 Method 對象表示的方法的類或接口的 Class 對象
Annotation[] getDeclaredAnnotations() 返回直接存在於此元素上的全部註釋

Constructor

boolean equals(Object obj) 將此 Constructor 對象與指定的對象進行比較
String getName() 以字符串形式返回此構造方法的名稱
Class<T> getDeclaringClass() 返回 Class 對象,該對象表示聲明由此 Constructor 對象表示的構造方法的類
int getModifiers() 以整數形式返回此 Constructor 對象所表示構造方法的 Java 語言修飾符
T newInstance(Object... initargs) 使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例
Class<?>[] getParameterTypes() 按照聲明順序返回一組 Class 對象,這些對象表示此 Constructor 對象所表示構造方法的形參類型
Type[] getGenericParameterTypes() 按照聲明順序返回一組 Type 對象,這些對象表示此 Constructor 對象所表示的方法的形參類型
相關文章
相關標籤/搜索