1.如何建立Class的執行個體(反射的源頭)
理解:
Class是一個對象,對應一個運行時類。相當於一個運行時類本身充當了Class的一個執行個體
過程:
源檔案經過編譯(javac.exe)這步,就需要進行類的載入(通過JVM的類的載入器)
記載到記憶體中的緩衝,每一個放入緩衝中的.class檔案就是一個Class執行個體。
Java.lang.Class是反射的源頭。
接下來涉及到的類都在java.lang.reflect子包下
如:Field MethodConstructor Type Package
通過Class執行個體調用getMethods擷取所有的方法,getContructors()擷取所有的Constructor
執行個體化Class的方法
1.調用運行時類的.class屬性如:Class clazz1=Person.class; ;
2.調用類的對象,調用其getClass方法 如:Person p=new Person(); Classclazz2=p.getClass();
3.調用Class靜態方法forName(String className)此方法報ClassNotFoundException如:; Class clazz3=Class.forName("1.txt");
4.通過類的載入器:ClassLoaderloader=this.getClass().getClassLoader(); Class clazz4=loader.loadClass("1.txt");
2.有了Class執行個體之後可以做什麼:(見demo)
2.1可以建立對應的運行時類的對象
2.2可以擷取對應的運行時類的完整的類的結構:屬性、方法、構造器、包、父類、介面、泛型、註解、異常、內部類。。。如:
Method[] m1=clazz,getMethods()擷取對應的運行時類(聲明的Public方法),(包含父類的)
Method[] m2=clazz.getDeclaredMethod()擷取對應的運行時類本身的所有公有或私人的方法(不包含父類)(任何許可權)
2.3可以調用運行時類中指定的結構(某個指定的屬性、方法、構造器)(見demo)
3.動態代理--反射的應用,體會反射的動態性
package myNetDemo;import javax.print.attribute.standard.Sides;public class Animal {private String name;public int age;static String desc="我是一個小動物";public Animal(){super();System.out.println("測試clazz.instance()調用的初始構造器是這個。");}//test怎樣調用private構造器,利用反射private Animal(String name,int age){super();this.name=name;this.age=age;}@Overridepublic String toString() {return "Animal [name=" + name + ", age=" + age + "]";}public static void info(){System.out.println("動物");}public String getName() {return name;}public void setName(String name) {this.name = name;}//為了測試調用私人方法的方法private int getAge() {return age;}public void setAge(int age) {this.age = age;}public static String getDesc() {return desc;}public static void setDesc(String desc) {Animal.desc = desc;}public void show(String desc){System.out.println("我是一個,"+desc);}}
package myNetDemo;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import org.junit.Test;public class TestReflection {// 調用指定的方法@Testpublic void test4() throws Exception {Class clazz = Class.forName("myNetDemo.Animal");Object obj = clazz.newInstance();Animal a = (Animal) obj;// 調用private方法Method m1 = clazz.getDeclaredMethod("getAge");m1.setAccessible(true);int age = (int) m1.invoke(a);// 方法的傳回值是getAge()的傳回值System.out.println(age);// 調用public方法Method m2 = clazz.getMethod("show", String.class);Object returnVal = m2.invoke(a, "小花貓");System.out.println(returnVal);//show方法的傳回值,若void則為null// 調用靜態方法staticMethod m3=clazz.getDeclaredMethod("info");m3.setAccessible(true);m3.invoke(a);m3.invoke(Animal.class);m3.invoke(null);}// 調用指定的屬性@Testpublic void test3() throws Exception {Class clazz = Class.forName("myNetDemo.Animal");Object obj = clazz.newInstance();Animal a = (Animal) obj;// 調用私人屬性Field f1 = clazz.getDeclaredField("name");f1.setAccessible(true);f1.set(a, "Jerry");// 調用共有的屬性Field f2 = clazz.getField("age");f2.set(a, 9);System.out.println(a);// 要擷取某個屬性,是擷取對象的屬性System.out.println(f2.get(a));// 調用靜態屬性Field f3 = clazz.getDeclaredField("desc");System.out.println(f3.get(Animal.class));System.out.println(f3.get(a));System.out.println(f3.get(null));}// 調用指定構造器調用運行時對象@Testpublic void test2() throws Exception {Class clazz = Animal.class;Constructor c = clazz.getDeclaredConstructor(String.class, int.class);// 調用私人方法c.setAccessible(true);// 設定存取權限Animal a = (Animal) c.newInstance("Tom", 10);System.out.println(a);}// 擷取運行時對象,方式一@Testpublic void test1() throws Exception {Class clazz = Class.forName("myNetDemo.Animal");Object obj = clazz.newInstance();// 建立運行時對象,預設調用的是空參構造器Animal a = (Animal) obj;System.out.println(a);}}