Java -- 類載入器&反射&代理
阿新 • • 發佈:2018-12-27
類載入&類載入器
類的載入描述:
反射&reflect
JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件。
-
Class類的獲取
/*for example*/ public class TestClass { public static void main(String[] args) throws ClassNotFoundException { /* 類的三種獲取方式 */ /* the first... */ Person p = new Person(); Class pClass = p.getClass(); System.out.println(pClass); /* the second... */ Class sClass = Person.class; System.out.println(sClass); /* the third... */ Class tClass = Class.forName("ReflectionTools.Person"); System.out.println(tClass); } }
-
Class類構造方法的獲取
/*for example*/ /* 僅僅顯示由public修飾的構造方法 */ Constructor[] con = tClass.getConstructors(); for (Object obj : con) System.out.println(obj); Constructor[] conAll = tClass.getDeclaredConstructors(); System.out.println("------- this is a dividing line --------"); /* 所有的構造方法都顯示出來. */ for (Object obj : conAll) System.out.println(obj); System.out.println("------- this is a dividing line --------");
-
Class類欄位的獲取
/*for example*/ 與構造方法完全一樣,用Field替換對應的部分即可。
-
Class類成員方法的獲取
/*for example*/ 不同之處在於getMethods方法獲取的是獲取的所有方法,包括父類的的public修飾的。 getDeclaredMethods是自己的所有修飾符修飾的成員方法。
-
使用帶Declared的函式獲取的函式是完整的,但是若需要使用指定的成員變數與成員方法,則可以利用反射。使用對應的帶引數的函式+函式名稱即可呼叫,若是非公有的,可以使用setAccessiable強制呼叫。
/*for example 非區域性的使用*/ /*PJO定義一個簡單的類*/ package ReflectionTools; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class Person { private String name; private int age; private String address; /* 私有的帶參構造方法。 */ private Person(String name, int age) { this.name = name; this.age = age; } public Person(String name) { this.name = name; } public Person(String name, int age, String address) { super(); this.name = name; this.age = age; this.address = address; } /* 無參構造方法. */ Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } private void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ", address=" + address + "]"; } } /*測試主函式*/ public class TestClass { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { /* 類的三種獲取方式 */ /* the first... */ Person p = new Person(); Class pClass = p.getClass(); System.out.println(pClass); /* the second... */ Class sClass = Person.class; System.out.println(sClass); /* the third... */ Class tClass = Class.forName("ReflectionTools.Person"); System.out.println(tClass); System.out.println("-------this is a dividing line--------"); /* 僅僅顯示由public修飾的構造方法 */ Constructor[] con = tClass.getConstructors(); for (Object obj : con) System.out.println(obj); Constructor[] conAll = tClass.getDeclaredConstructors(); System.out.println("------- this is a dividing line --------"); /* 所有的構造方法都顯示出來. */ for (Object obj : conAll) System.out.println(obj); System.out.println("------- this is a dividing line --------"); /* 無引數構造方法的使用。 */ Constructor conSpecific = tClass.getDeclaredConstructor(); Object obj = conSpecific.newInstance(); /*呼叫private修飾的變數*/ Field fieldSpecific = tClass.getDeclaredField("name"); fieldSpecific.setAccessible(true); fieldSpecific.set(obj, "Tom"); /* 呼叫非public修飾的成員方法 */ Method methodSpecific = tClass.getDeclaredMethod("setAge", int.class); methodSpecific.setAccessible(true); methodSpecific.invoke(obj, 5); System.out.println(obj); } } /*控制檯輸出結果為:*/ class ReflectionTools.Person class ReflectionTools.Person class ReflectionTools.Person -------this is a dividing line-------- public ReflectionTools.Person(java.lang.String,int,java.lang.String) public ReflectionTools.Person(java.lang.String) ------- this is a dividing line -------- private ReflectionTools.Person(java.lang.String,int) ReflectionTools.Person() public ReflectionTools.Person(java.lang.String,int,java.lang.String) public ReflectionTools.Person(java.lang.String) ------- this is a dividing line -------- Person [name=Tom, age=5, address=null]
-
反射的應用
-
構造一個動態的物件呼叫動態的方法:
/*for example*/ /**config.ini是配置class類和對應方法的。/ package ReflectionTools; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Properties; /*config.ini*/ /*content: className = ReflectionTools.personTest classValue = hobby */ class animal { private String name; public animal() { } public void show() { System.out.println(this.name + "this is animailShow!"); } } class personTest { private String name; private int age; private String address; public personTest() { } public void hobby() { System.out.println(this.name + "this is a personHobby!" + this.age + this.address); } } public class ReflectionApp { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { /* 使用throws不必初始化,直接異常彈出,這樣的目的是為了防止空指標異常。 */ FileReader fileReader = new FileReader("config.ini"); Properties keyValue = new Properties(); keyValue.load(fileReader); fileReader.close(); String getNameID = keyValue.getProperty("className"); String getValueID = keyValue.getProperty("classValue"); Class classFiles = Class.forName(getNameID); Constructor con = classFiles.getConstructor(); Object obj = con.newInstance(); Method meTest = classFiles.getDeclaredMethod(getValueID); meTest.invoke(obj); } }
-
反射修改泛型
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; /* * 我給你ArrayList<Integer>的一個物件,要求在這個集合中新增一個字串資料。 */ public class ArrayLis{ public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { /*建立集合物件*/ ArrayList<Integer> array = new ArrayList<Integer>(); Class classfile = array.getClass(); /*集合ArrayList的class檔案物件*/ Method me = classfile.getMethod("add", Object.class); me.invoke(array, "hello"); /*呼叫array的add方法,傳入的值是hello.*/ me.invoke(array, "world"); System.out.println(array); } }
-
-
Proxy代理物件
- 描述:代理一個物件的操作,結合InvocationHandler介面,只能實現對介面的代理。若要對類進行代理需要使用cglib。
- tip:該類代理不會再框架中使用,故而略…