今日分享開始啦,請大家多多指教~
這篇文章給大家先簡簡單單地說下類的載入,以及具體實現,可以自己操作一下哦!
類的載入
在程式執行後,首次使用某個類,會把這個類的位元組碼檔案讀取到記憶體,並且會將這個類的所有資訊存到一個Class物件中。
簡單步驟:
1:jvm執行程式碼,例如讀到 new Student()
2 : 讀取Student的位元組碼檔案
3:把位元組碼檔案的內容(讀取成位元組碼物件)儲存到方法區(以前的說法),1。8以後叫做元空間(貌似)
4:最後類載入完成以後,在堆空間建立記憶體空間。
類的載入時機(下面六種)
建立類的例項。(new 一個類)
類的靜態變數,或者為靜態變數賦值。
類的靜態方法。
使用反射方式來強制建立某個類或介面對應的java。lang。Class物件。
初始化某個類的子類。
直接使用java。exe命令來執行某個主類。(編譯 javac 類名。java, 執行 java。類名)
今天的反射也屬於類載入時機的一種
先上程式碼:
類載入時機程式碼演示
1。 建立類的例項。 靜態程式碼塊隨著類的載入而載入,並且只執行一次。
2。 類的靜態變數,或者為靜態變數賦值。
3。 類的靜態方法。
4。反射透過 Class。forName(“全類名”) 進行反射
5。透過子類例項
執行結果
都證明了這個stu類被載入了。
類載入器(暫時先了解了解)
下面說說類載入器,類載入器是負責將實際空間中的某個class檔案讀取到記憶體中並且生成Class的物件。
Java中有三種類載入器,它們分別用於載入不同種類的class:
Java中有三種類載入器,它們分別用於載入不同種類的class:
啟動類載入器(Bootstrap ClassLoader):用於載入系統類庫
擴充套件類載入器(Extension ClassLoader):用於載入擴充套件類庫
應用程式類載入器(Application ClassLoader):用於載入我們自定義類的載入器。
進去程式碼看看,我們是如何獲得類載入器的
再點進getClassLoader()方法看看jdk是怎麼描述的
圖中看到,一些實現可能使用null來表示引導類載入器,可能在此類中的實現返回null。
舉個例子。
好了,接下來該回到反射的主題
反射的概念
它一種機制,利用這個機制就可以在程式中對類進行解析,並且可以操作類中所有成員(變數,方法,構造方法)。
使用反射需要一個前提,獲取需要反射的那個類的位元組碼物件。
Class物件的獲取方式
透過類名。class獲得
透過物件名。getClass()方法獲得
透過Class類的靜態方法獲得: static Class forName(“類全名”)
Tips:每個類的Class物件都只有一個
Class類常用的方法
String getSimpleName(); 獲取類名字串
String getName(); 獲取全類名字串
建立類的物件
1.T newInstance(): 建立Class物件關聯類的物件。
2.透過Constructor類來建立物件
首先要獲取構造器類
Class類中與Constructor相關的方法
1。Constructor getConstructor(Class… parameterTypes)
* 根據引數型別獲得對應的Constructor物件。
getConstructor()的原始碼描述
上個使用的程式碼
Java
/**
* 先用getConstructor() 獲取Constructor
* 再透過這個物件例項T。 沒有引數的用法
* @throws Exception
*/
@Test
public void getPublicConstructorWithoutParameter() throws Exception {
Class
//先獲取無參構造類物件。
Constructor
//再透過這個例項方法,例項這個類
Student student = constructor。newInstance();
}
/**
* 先用getConstructor() 獲取Constructor
* 再透過這個物件例項T。 有引數的用法
* @throws Exception
*/
@Test
public void getPublicConstructor() throws Exception {
Class
//獲取有參構造類
Constructor
//輸入引數例項化Student類
Student student = constructor。newInstance(1);
}
如圖所述,如果傳入了沒有相關引數過載的構造器,會報NoSuchMethodException異常
2。Constructor getDeclaredConstructor(Class… parameterTypes)
* 根據引數型別獲得對應的Constructor物件
* 可以是public、protected、(預設)、private修飾符的構造方法。
* 如果是被protected、(預設)、private修飾符修飾的構造器,需要確定本身能否訪問到,如果不能訪問到就要設定許可權,用setAccessible(true)。
暴力獲取構造器,能獲取包括public protected default private
透過getDeclaredConstructor()暴力獲取Student類中除了public其他修飾符的構造器,但這個構造類物件需要設定許可權,setAccessible(true)
具體要不要設定,得看這個修飾符本身能否訪問到相關資源。
圖上是個反例。
3。Constructor[] getConstructors()
獲得類中的所有構造方法物件,只能獲得public的
上程式碼:
透過getConstructors()獲取所有public修飾的構造器類物件。
@Test
public void getAllPublicConstructor(){
Class
Constructor
for (Constructor
System。out。println(constructor);
}
}
遍歷列印的結果:
4。Constructor[] getDeclaredConstructors()
獲得類中的所有構造方法物件
可以是public、protected、(預設)、private修飾符的構造方法。
透過getDeclaredConstructors()獲取所有p修飾的構造器類物件。
@Test
public void getAllAccessConstructor(){
Class
Constructor
for (Constructor
System。out。println(constructor);
}
}
遍歷列印的結果:
獲取成員方法
接下來的部分就不放程式碼演示了,就提供下api。
1 **Method getMethod(String name,Class。。。args);**
方法名和引數型別獲得對應的成員方法物件,只能獲得public的
2 **Method getDeclaredMethod(String name,Class。。。args);**
根據方法名和引數型別獲得對應的成員方法物件,包括public、protected、(預設)、private的
3 **Method[] getMethods();**
獲得類中的所有成員方法物件,返回陣列,只能獲得public修飾的且包含父類的
4**Method[] getDeclaredMethods();**
獲得類中的所有成員方法物件,返回陣列,只獲得本類的,包括public、protected、(預設)、private的
透過反射訪問成員變數
Method物件常用方法
Object invoke(Object obj, Object。。。 args)
* 呼叫指定物件obj的該方法
* args:呼叫方法時傳遞的引數
void setAccessible(true)
設定“暴力訪問”——是否取消許可權檢查,true取消許可權檢查,false表示不取消
透過反射獲取類的成員變數
Class類中與Field相關的方法
Field getField(String name);
* 根據成員變數名獲得對應Field物件,只能獲得public修飾
Field getDeclaredField(String name);
* 根據成員變數名獲得對應Field物件,包括public、protected、(預設)、private的
Field[] getFields();
* 獲得所有的成員變數對應的Field物件,只能獲得public的
Field[] getDeclaredFields();
* 獲得所有的成員變數對應的Field物件,包括public、protected、(預設)、private的
透過反射訪問成員變數
Field物件常用方法
**void set(Object obj, Object value)**
**void setInt(Object obj, int i)**
**void setLong(Object obj, long l)**
**void setBoolean(Object obj, boolean z)**
**void setDouble(Object obj, double d)**
**Object get(Object obj)
intgetInt(Object obj)**
**long getLong(Object obj)**
**boolean getBoolean(Object ob)**
**double getDouble(Object obj)**
**void setAccessible(true);暴力反射,設定為可以直接訪問私有型別的屬性。**
**Class getType(); 獲取屬性的型別,返回Class物件。**
今日份分享已結束,請大家多多包涵和指點!