第十三章:Java_反射机制
反射?
類的加載過程:
1.如何創建Class的實例(重點)
1.1過程:源文件經過編譯(javac.exe)以后,得到一個或多個.class文件。.class文件經過運行(java.exe)這步,
就需要進行類的加載(通過JVM的類的加載器),記載到內存中的緩存。每一個放入緩存中的.class文件就是一個Class的實例!
1.2 Class的一個對象,對應著一個運行時類。相當于一個運行時類本身充當了Class的一個實例。
1.3 java.lang.Class是反射的源頭。 接下來涉及到反射的類都在java.lang.reflect子包下。如:Field Method Constructor Type Package..
當通過Class的實例調用getMethods() —>Method , getConstructors() —->Constructor
1.4實例化Class的方法(三種):
// 1.調用運行時類的.class屬性Class clazz1 = Person.class;System.out.println(clazz1);Class clazz2 = Creator.class;System.out.println(clazz2);// 2.通過運行時類的對象,調用其getClass()方法Person p = new Person();Class clazz3 = p.getClass();System.out.println(clazz3);// 3.調用Class的靜態方法forName(String className)。此方法報ClassNotFoundExceptionString className = "com.atguigu.java.Person";Class clazz4 = Class.forName(className);System.out.println(clazz4);2.Class的實例–應用一
應用一:可以創建對應的運行時類的對象(重點)
//獲取運行時類的對象:方法一@Testpublic void test1() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;System.out.println(a);}//調用指定的構造器創建運行時類的對象@Testpublic void test2() throws Exception{Class clazz = Animal.class;Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);cons.setAccessible(true);Animal a = (Animal)cons.newInstance("Tom",10);System.out.println(a);}3.Class的實例–應用二
應用二:獲取對應的運行時類的完整的類的結構:屬性、方法、構造器、包、父類、接口、泛型、注解、異常、內部類。。。
如:Method[] m1 = clazz.getMethods() :獲取到對應的運行時類中聲明的權限為public的方法(包含其父類中的聲明的public)
Method[] m2 = clazz.getDeclaredMethods():獲取到對應的運行時類中聲明的所有的方法(①任何權限修飾符修飾的都能獲取②不含父類中的)
4.Class的實例–應用三
應用三:調用對應的運行時類中指定的結構(某個指定的屬性、方法、構造器)(重點)
//調用指定屬性 @Test public void test3() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;//調用非public的屬性Field f1 = clazz.getDeclaredField("name");f1.setAccessible(true);f1.set(a, "Jerry");//調用public的屬性Field f2 = clazz.getField("age");f2.set(a, 9);System.out.println(f2.get(a));System.out.println(a);//調用static的屬性Field f3 = clazz.getDeclaredField("desc");System.out.println(f3.get(null)); }//調用指定的方法 @Test public void test4() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;//調用非public的方法Method m1 = clazz.getDeclaredMethod("getAge");m1.setAccessible(true);int age = (Integer)m1.invoke(a);System.out.println(age);//調用public的方法Method m2 = clazz.getMethod("show", String.class);Object returnVal = m2.invoke(a,"金毛");System.out.println(returnVal);//調用static的方法Method m3 = clazz.getDeclaredMethod("info");m3.setAccessible(true); // m3.invoke(Animal.class);m3.invoke(null); }5.動態代理—反射的應用
體會反射的動態性
代理設計模式的原理:
使用一個代理將對象包裝起來, 然后用該代理對象取代原始對象. 任何對原始對象的調用都要通過代理. 代理對象決定是否以及何時
將方法調用轉到原始對象上
靜態代理:要求被代理類和代理類同時實現相應的一套接口;通過代理類的對象調用重寫接口的方法時,實際上執行的是被代理類的同樣的
方法的調用。
靜態代理模式
動態代理:在程序運行時,根據被代理類及其實現的接口,動態的創建一個代理類。當調用代理類的實現的抽象方法時,就發起對被代理類同樣
方法的調用。
涉及到的技術點:①提供一個實現了InvocationHandler接口實現類,并重寫其invoke()方法 ②Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),h);
注:obj:被代理類對象 ; h:實現了InvocationHandler接口的實現類的對象
動態代理的使用
動態代理與AOP
interface Human {void info();void fly(); }// 被代理類 class SuperMan implements Human {public void info() {System.out.println("我是超人!我怕誰!");}public void fly() {System.out.println("I believe I can fly!");} }class HumanUtil {public void method1() {System.out.println("=======方法一=======");}public void method2() {System.out.println("=======方法二=======");} }class MyInvocationHandler implements InvocationHandler {Object obj;// 被代理類對象的聲明public void setObject(Object obj) {this.obj = obj;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {HumanUtil h = new HumanUtil();h.method1();Object returnVal = method.invoke(obj, args);h.method2();return returnVal;} }class MyProxy {// 動態的創建一個代理類的對象public static Object getProxyInstance(Object obj) {MyInvocationHandler handler = new MyInvocationHandler();handler.setObject(obj);return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);} }public class TestAOP {public static void main(String[] args) {SuperMan man = new SuperMan();//創建一個被代理類的對象Object obj = MyProxy.getProxyInstance(man);//返回一個代理類的對象Human hu = (Human)obj;hu.info();//通過代理類的對象調用重寫的抽象方法System.out.println();hu.fly();//*********NikeClothFactory nike = new NikeClothFactory();Object obj1 = MyProxy.getProxyInstance(nike);ClothFactory cloth = (ClothFactory)obj1;cloth.productCloth();} }效果:
反射例子
public class TestReflection {//調用指定的方法@Testpublic void test4() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;//調用非public的方法Method m1 = clazz.getDeclaredMethod("getAge");m1.setAccessible(true);int age = (Integer)m1.invoke(a);System.out.println(age);//調用public的方法Method m2 = clazz.getMethod("show", String.class);Object returnVal = m2.invoke(a,"金毛");System.out.println(returnVal);//調用static的方法Method m3 = clazz.getDeclaredMethod("info");m3.setAccessible(true); // m3.invoke(Animal.class);m3.invoke(null);}//調用指定屬性@Testpublic void test3() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;//調用非public的屬性Field f1 = clazz.getDeclaredField("name");f1.setAccessible(true);f1.set(a, "Jerry");//調用public的屬性Field f2 = clazz.getField("age");f2.set(a, 9);`System.out.println(f2.get(a));System.out.println(a);//調用static的屬性Field f3 = clazz.getDeclaredField("desc");System.out.println(f3.get(null));}//調用指定的構造器創建運行時類的對象@Testpublic void test2() throws Exception{Class clazz = Animal.class;Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);cons.setAccessible(true);Animal a = (Animal)cons.newInstance("Tom",10);System.out.println(a);}//獲取運行時類的對象:方法一@Testpublic void test1() throws Exception{Class clazz = Class.forName("com.atguigu.review.Animal");Object obj = clazz.newInstance();Animal a = (Animal)obj;System.out.println(a);} }如何獲取:
public class TestReflection {//關于類的加載器:ClassLoader@Testpublic void test5() throws Exception{ClassLoader loader1 = ClassLoader.getSystemClassLoader();System.out.println(loader1);ClassLoader loader2 = loader1.getParent();System.out.println(loader2);ClassLoader loader3 = loader2.getParent();System.out.println(loader3);Class clazz1 = Person.class;ClassLoader loader4 = clazz1.getClassLoader();System.out.println(loader4);String className = "java.lang.String";Class clazz2 = Class.forName(className);ClassLoader loader5 = clazz2.getClassLoader();System.out.println(loader5);//掌握如下//法一:ClassLoader loader = this.getClass().getClassLoader();InputStream is = loader.getResourceAsStream("com\\atguigu\\java\\jdbc.properties");//法二: // FileInputStream is = new FileInputStream(new File("jdbc1.properties"));Properties pros = new Properties();pros.load(is);String name = pros.getProperty("user");System.out.println(name);String password = pros.getProperty("password");System.out.println(password);}//如何獲取Class的實例(3種)@Testpublic void test4() throws ClassNotFoundException{//1.調用運行時類本身的.class屬性Class clazz1 = Person.class;System.out.println(clazz1.getName());Class clazz2 = String.class;System.out.println(clazz2.getName());//2.通過運行時類的對象獲取Person p = new Person();Class clazz3 = p.getClass();System.out.println(clazz3.getName());//3.通過Class的靜態方法獲取.通過此方式,體會一下,反射的動態性。String className = "com.atguigu.java.Person";Class clazz4 = Class.forName(className); // clazz4.newInstance();System.out.println(clazz4.getName());//4.(了解)通過類的加載器ClassLoader classLoader = this.getClass().getClassLoader();Class clazz5 = classLoader.loadClass(className);System.out.println(clazz5.getName());System.out.println(clazz1 == clazz3);//trueSystem.out.println(clazz1 == clazz4);//trueSystem.out.println(clazz1 == clazz5);//true}/** java.lang.Class:是反射的源頭。* 我們創建了一個類,通過編譯(javac.exe),生成對應的.class文件。之后我們使用java.exe加載(JVM的類加載器完成的)* 此.class文件,此.class文件加載到內存以后,就是一個運行時類,存在在緩存區。那么這個運行時類本身就是一個Class的實例!* 1.每一個運行時類只加載一次!* 2.有了Class的實例以后,我們才可以進行如下的操作:* 1)*創建對應的運行時類的對象* 2)獲取對應的運行時類的完整結構(屬性、方法、構造器、內部類、父類、所在的包、異常、注解、...)* 3)*調用對應的運行時類的指定的結構(屬性、方法、構造器)* 4)反射的應用:動態代理*/@Testpublic void test3(){Person p = new Person();Class clazz = p.getClass();//通過運行時類的對象,調用其getClass(),返回其運行時類。System.out.println(clazz);}//有了反射,可以通過反射創建一個類的對象,并調用其中的結構@Testpublic void test2() throws Exception{Class clazz = Person.class;// Class clazz1 = String.class;//1.創建clazz對應的運行時類Person類的對象Person p = (Person)clazz.newInstance();System.out.println(p);//2.通過反射調用運行時類的指定的屬性//2.1Field f1 = clazz.getField("name");f1.set(p,"LiuDeHua");System.out.println(p);//2.2Field f2 = clazz.getDeclaredField("age");f2.setAccessible(true);f2.set(p, 20);System.out.println(p);//3.通過反射調用運行時類的指定的方法Method m1 = clazz.getMethod("show");m1.invoke(p);Method m2 = clazz.getMethod("display",String.class);m2.invoke(p,"CHN");}//在有反射以前,如何創建一個類的對象,并調用其中的方法、屬性@Testpublic void test1(){Person p = new Person(); // Person p1 = new Person();p.setAge(10);p.setName("TangWei");System.out.println(p);p.show(); // p.display("HK");} }總結
以上是生活随笔為你收集整理的第十三章:Java_反射机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: The connection to ad
- 下一篇: 方立勋_30天掌握JavaWeb_XML