詳述獲取位元組碼檔案及其內容的方法
阿新 • • 發佈:2019-01-21
1 簡述
Java 的反射機制是指:
- 在執行狀態中,對任意一個類(class檔案),都能知道這個類的所有屬性和方法;對任意一個物件,都能呼叫這個物件的方法和屬性。
簡單點說,這種動態的獲取資訊和動態的呼叫物件的方法的功能就是 Java 的反射機制。利用 Java 的反射機制,我們可以很容易的獲取類的詳細資訊,如建構函式、成員變數和成員函式等。
2 獲取位元組碼檔案
首先,構造一個實體類:
/**
* @Author Charies Guo
* @Date 2017/7/29,下午5:15
* @Description Person Entity
*/
public class Person {
private String name;
private int age;
public Person() {
System.out.println("Person run");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Person param run ... " + this.name + " is " + this.age + " years old!" );
}
public void showInfo(String name, int age){
this.name = name;
this.age = age;
System.out.println("Show Peron Info : " + this.name + " is " + this.age + " years old!");
}
public void playBadminton(){
System.out.println("Let's play badminton, go go go..." );
}
}
接下來,以 Person 類為例,演示獲取位元組碼檔案的 3 種方式:
/**
* @Author Charies Guo
* @Date 2017/7/29,下午5:23
* @Description Get class file
*/
public class GetClassFile {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println("第 1 種獲取方式:");
getClassObject_1();
System.out.println("第 2 種獲取方式:");
getClassObject_2();
System.out.println("第 3 種獲取方式:");
getClassObject_3();
}
/**
* 利用 Object 類中的 getClass 方法
* 用這個方法時,必須明確具體的類,並建立物件
* 比較麻煩
*/
public static void getClassObject_1() {
Person p = new Person();
Class clazz = p.getClass();
Person p1 = new Person("Charies",18);
Class clazz1 = p1.getClass();
System.out.println(clazz == clazz1);
}
/**
* 任何資料型別都具備一個靜態屬性
* 通過 .class 來獲取對應的 Class 物件
* 擴充套件性較差
*/
public static void getClassObject_2() {
Class clazz = Person.class;
Class clazz1 = Person.class;
System.out.println(clazz == clazz1);
}
/**
* 通過給定的類的字串名稱就可以獲取該類的位元組碼檔案,更利於擴充套件
* 可以用 Class 類中的 forName() 方法來完成
*/
public static void getClassObject_3() throws ClassNotFoundException {
// 包名一定要寫全,否則會報 java.lang.ClassNotFoundException 異常
String className = "Person";
Class clazz = Class.forName(className);
System.out.println(clazz);
}
}
執行上述程式碼,結果如下圖所示:
3 獲取位元組碼檔案的內容
3.1 獲取建構函式
import java.lang.reflect.Constructor;
/**
* @Author Charies Guo
* @Date 2017/7/29,下午6:07
* @Description Get class constructor
*/
public class GetClassConstructor {
public static void main(String[] args) throws Exception {
createNewObject_1();
createNewObject_2();
}
/**
* 獲取預設建構函式
*/
public static void createNewObject_1() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String name = "Person";
// 尋找該名稱類檔案,並加進記憶體,產生 Class 物件
Class clazz = Class.forName(name);
// 產生該類的例項物件(空參)
Object obj = clazz.newInstance();
}
/**
* 獲取帶引數的建構函式
*/
public static void createNewObject_2() throws Exception {
/**
* 當獲取指定名稱對應類中的實體物件時,而且該物件的初始化不適用空參的建構函式
* 可以先通過該類的位元組碼檔案物件,獲取空參的建構函式
* 該方法為:getConstructor(parameterTypes)
*/
// 包名一定要寫全,否則會報 java.lang.ClassNotFoundException 異常
String name = "Person";
// 找尋該名稱類檔案,並加進記憶體,產生 Class 物件
Class clazz = Class.forName(name);
// 獲取指定的建構函式物件
Constructor constructor = clazz.getConstructor(String.class, int.class);
// 通過該構造器物件的 newInstance 方法進行物件的初始化
constructor.newInstance("Charies", 18);
}
}
3.2 獲取成員變數
import java.lang.reflect.Field;
/**
* @Author Charies Guo
* @Date 2017/7/29,下午6:15
* @Description Get class field
*/
public class GetClassField {
public static void main(String[] args) throws Exception {
getField();
}
/**
* 獲取位元組碼檔案中的成員變數
*/
public static void getField() throws Exception {
Class clazz = Class.forName("Person");
Field field = null;
// 獲取本類欄位,包含私有
field = clazz.getDeclaredField("age");
// 對私有欄位的訪問取消許可權檢查,可稱之為暴力訪問
field.setAccessible(true);
Object obj = clazz.newInstance();
field.set(obj, Integer.valueOf(18));
Object o = field.get(obj);
System.out.println(o);
}
}
3.3 獲取成員函式
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @Author Charies Guo
* @Date 2017/7/29,下午6:22
* @Description Get class method
*/
public class GetClassMethod {
public static void main(String[] args) throws Exception {
System.out.println("第 1 個方法:");
getMethod_1();
// System.out.println("第 2 個方法:");
// getMethod_2();
// System.out.println("第 3 個方法:");
// getMethod_3();
}
/**
* 獲取指定 Class 中的公有函式
*/
public static void getMethod_1() throws Exception {
Class clazz = Class.forName("Person");
// 獲取的都是類中的公有方法
Method[] methods = clazz.getMethods();
// 獲取本類中的所有方法
methods = clazz.getDeclaredMethods();
Method[] var5 = methods;
int var4 = methods.length;
for (int var3 = 0; var3 < var4; ++var3) {
Method method = var5[var3];
System.out.println(method);
}
}
/**
* 獲取指定 Class 中的空參函式
*/
public static void getMethod_2() throws Exception {
Class clazz = Class.forName("Person");
// 獲取空引數的方法
Method method = clazz.getMethod("playBadminton");
Constructor constructor = clazz.getConstructor(new Class[]{String.class, Integer.TYPE});
Object obj = constructor.newInstance(new Object[]{"Charies", Integer.valueOf(18)});
method.invoke(obj, (Object[]) null);
}
/**
* Integer.TYPE 等價於 int.class
*/
public static void getMethod_3() throws Exception {
Class clazz = Class.forName("Person");
Method method = clazz.getMethod("showInfo", new Class[]{String.class, Integer.TYPE});
Object obj = clazz.newInstance();
method.invoke(obj, new Object[]{"Charies", Integer.valueOf(18)});
}
}