java反射初學習
java反射初學習
“程式執行時,允許改變程式結構或變數型別,這種語
言稱為動態語言”,如Python,Ruby是動態語言;顯然
C++,Java,C#不是動態語言,但是JAVA有著一個非常
突出的動態相關機制:Reflection。
JAVA反射機制是在執行狀態中,對於任意一個類,都能
夠知道這個類的所有屬性和方法;對於任意一個物件,
都能夠呼叫它的任意一個方法和屬性;這種動態獲取的
資訊以及動態呼叫物件的方法的功能稱為java語言的反
射機制,很多優秀的開源框架都是通過反射完成的。
Java反射機制,可以實現以下功能:
①在執行時判斷任意一個物件所屬的類;
②在執行時構造任意一個類的物件;
③在執行時判斷任意一個類所具有的成員變數和方法;
④在執行時呼叫任意一個物件的方法;
⑤生成動態代理;
可變引數
/**
\* 入門級示例:通過物件獲取 包名.類名
\* @author Administrator
*/
public class Simple {
public static void main(String[] args) {
Simple s=new Simple();
System.out.println(s.2.getName());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
當我們能夠確定一系列引數的型別,型別必須是統一
的, 但是我們確定不了引數的個數的時候,我們可以使
用可變引數。可變代表個數可變[0,+),如果一個方法
中帶有可變引數,這個可變引數只能在引數列表最後。
獲取源頭Class(重點)
所有類的物件其實都是Class**的例項。**這個 Class 例項
可以理解為類的模子,就是包含了類的結構資訊,類似
於圖紙。我們日常生活中,需要創造一個產品,如想山
寨一個iphone手機,怎麼辦?有三種方式可以實現:
⑴買個iphone手機,拆的七零八落的,開始山寨;
⑵到iphone工廠參觀,拿到iphone磨具,開始山寨;
⑶跑到美國盜取iphone的圖紙,開始山寨,最後一種最
暴力,最爽。
同理,獲取類的Class物件也有三種方式
⑴Class.forName(”包名.類名”) //一般儘量採用該形式
(2)類.class
(3)物件.getClass()
類載入器(瞭解)
類的生命週期
在一個類編譯完成之後,下一步就需要開始使用類,如
果要使用一個類,肯定離不開JVM。在程式執行中JVM通
過裝載,連結,初始化這3個步驟完成。
從類的生命週期而言,一個類包括如下階段:
載入、驗證、準備、初始化和解除安裝這5個階段的順序是確
定的,類的載入過程必須按照這種順序進行
類的裝載是通過 類載入器 完成的,載入器將 .class 文
件的二進位制檔案裝入JVM的方法區,並且在堆區建立描
述這個類的 java.lang.Class 物件。用來封裝資料。
但是同一個類只會被類裝載器裝載一次。
連結就是把二進位制資料組裝為可以執行的狀態。連結分
為校驗,準備,解析這3個階段
類載入器
顧名思義,類載入器(class loader)用來載入 Java 類到
Java 虛擬機器中。一般來說,Java 虛擬機器使用 Java 類的
方式如下:Java 源程式(.java 檔案)在經過 Java 編譯
器編譯之後就被轉換成 Java 位元組程式碼(.class 檔案)。
類載入器負責讀取 Java 位元組程式碼,並轉換成
java.lang.Class 類的一個例項。每個這樣的例項用
來表示一個 Java 類。通過此例項的 newInstance()
方法就可以創建出該類的一個物件。實際的情況可能更
加複雜,比如 Java 位元組程式碼可能是通過工具動態生成
的,也可能是通過網路下載的。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-f173Onk3-1603201534777)(C:\Users\lwf\AppData\Roaming\Typora\typora-user-images\image-20201020214106170.png)]
在java中有三種類類載入器:
⑴ Bootstrap ClassLoader 此載入器採用c++編寫,一般開
發中很少見。⑵ Extension ClassLoader 用來進行擴充套件類的載入,一般
對應的是jre\lib\ext目錄中的類
⑶ AppClassLoader 載入classpath指定的類,是最常用的
載入器。同時也是java中預設的載入器。 瞭解即可。
public static void main(String[] args) throws
Exception {
System.out.println("類載入器
"+ClassLoader.class.getClassLoader().getClass(
).getName());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
反射的運用
package com.lwf; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @author lwf * @title: RefTest * @projectName Learn * @description: 反射 * @date 2020/10/2019:51 */ public class RefTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, CloneNotSupportedException, IOException, NoSuchFieldException { //new物件 Student student0=new Student(); student0.setName("lwf"); student0.setAge(18); student0.setClassName("class 1"); System.out.println(student0); Class c=Class.forName("com.lwf.Student"); Constructor[] constructors = c.getDeclaredConstructors(); for(Constructor c1 : constructors){ System.out.println(c1); } Field[] declaredFields = c.getDeclaredFields(); System.out.println("屬性"); for(Field field:declaredFields){ System.out.println(field.getName()+","+field.getType()); } //修改訪問許可權,將私有屬性直接修改值 Field field = c.getDeclaredField("name"); field.setAccessible(true); field.set(student0, "羅衛飛"); System.out.println(student0); //呼叫方法 Method method=c.getMethod("getName"); System.out.println(method.invoke(student0)); //反射獲取物件 Student student1= (Student)c.getConstructor(String.class,Integer.class,String.class).newInstance("lwf",18,"一班"); Student student= (Student)c.getConstructor().newInstance(); System.out.println(student); System.out.println(student1); //克隆物件 繼承Coneable介面 Student student2=(Student