反射機(jī)制是什么?
反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有的屬性和方法
;對于任意一個(gè)對象,都能夠調(diào)用他的一個(gè)方法和屬性,這種動(dòng)態(tài)獲取的信息以及
動(dòng)態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。
反射機(jī)制能做什么?
反射機(jī)制主要提供以下功能
√ 在運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類
√ 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對象
√ 在運(yùn)行時(shí)判斷任意一個(gè)類所具有的的屬性和方法
√ 在運(yùn)行時(shí)調(diào)用一個(gè)對象的方法
√ 生成動(dòng)態(tài)代理
通過一個(gè)對象獲得完整的包名和類名
package com.hzg;public class TestReflect { public static void main(String[] args) throws Exception { TestReflect testReflect = new TestReflect(); System.out.println(testReflect.getClass().getName()); // 結(jié)果 com.hzg.TestReflect } }
通過一個(gè)對象獲得完整的屬性、方法
Class clazz = Person.class();//1、創(chuàng)建clazz對象的運(yùn)行時(shí)類Person對象Person p = (Person)clazz.getInstance();//2、通過反射調(diào)用運(yùn)行時(shí)的指定屬性Filed f1 = clazz.getField("name"); f1.set(p,"LiudeHua");//3、通過反射調(diào)用運(yùn)行時(shí)的指定的方法Method m1 = clazz.getMethod("show",String.class); m1.invoke(p,"CHN");
注意:Class可不是關(guān)鍵字class,Class是類名字,class是個(gè)關(guān)鍵字標(biāo)識(shí)是類
獲取class的實(shí)例(3種方式)
?、僬{(diào)用運(yùn)行時(shí)類本身的.class屬性
Class clazz = Person.class;
?、谕ㄟ^運(yùn)行時(shí)類的對象獲取
Person p = new Person();
Class clazz = p.getClass();
?、弁ㄟ^class的靜態(tài)方法獲取
Class clazz = Class.forName("com.hzg.TestReflect");
package com.hzg;public class TestReflect { public static void main(String[] args) throws Exception { Class<?> class1 = null; Class<?> class2 = null; Class<?> class3 = null; // ① 靜態(tài)方法(一般采用這種形式) class1 = Class.forName("com.hzg.TestReflect"); // ② 運(yùn)行時(shí)類的對象獲取 class2 = new TestReflect().getClass(); // ③ 類本身.class屬性 class3 = TestReflect.class; System.out.println("類名稱 " + class1.getName()); System.out.println("類名稱 " + class2.getName()); System.out.println("類名稱 " + class3.getName()); } }
獲取一個(gè)對象的父類與實(shí)現(xiàn)的接口
1 package com.hzg; 2 import java.io.Serializable; 3 public class TestReflect implements Serializable { 4 private static final long serialVersionUID = -2862585049955236662L; 5 public static void main(String[] args) throws Exception { 6 Class<?> clazz = Class.forName("com.hzg.TestReflect"); 7 // 取得父類 8 Class<?> parentClass = clazz.getSuperclass(); 9 System.out.println("clazz的父類為:" + parentClass.getName());10 // clazz的父類為: java.lang.Object11 // 獲取所有的接口12 Class<?> intes[] = clazz.getInterfaces();13 System.out.println("clazz實(shí)現(xiàn)的接口有:");14 for (int i = 0; i < intes.length; i++) {15 System.out.println((i + 1) + ":" + intes[i].getName());16 }17 }18 }
有了class實(shí)例以后,可以做什么呢?
?、?可以創(chuàng)建對應(yīng)運(yùn)行時(shí)類的對象
?、?獲取對應(yīng)運(yùn)行是類的完整的類的結(jié)構(gòu):屬性、方法、構(gòu)造器、包、泛型、注解、異常、內(nèi)部類。
如 Method[] m1 = clazz.getMethods():獲取類和父類的所有public方法
Method[] m1 = clazz.getDeclaredMethods():所有修飾符方法
但是不含父類,只有這個(gè)類的中所有修飾符方法
?、?調(diào)用運(yùn)行是類中指定的結(jié)構(gòu)(屬性、方法、構(gòu)造器)
√ 獲取指定屬性:Field name = clazz.getField("name");
√ 設(shè)置指定public屬性:name.set(p,"hzg");
√ 設(shè)置指定private屬性:
Field name = clazz.geDeclaredtField("name");
name.setAccessible(true);
name.set(p,"hzg");
√ 獲取指定的方法:Method m1 = clazz.getMethod("show");
√ 調(diào)用指定的方法:
Object obj = m1.invoke(p); 返回類型就是方法的返回類型
√ 調(diào)用靜態(tài)方法:m1.invoke(Person.class);
√ 調(diào)用帶參數(shù)的指定方法:
Method m1 = clazz.getDeclatedMethod("show1",String.class);
Object obj = m1.invoke(p,"hzg");
√ 調(diào)用構(gòu)造器:Constructor con = clazz.getDeclaredConstructor();
√ 調(diào)用帶參數(shù)構(gòu)造器,和帶參數(shù)方法一致
Java反射的應(yīng)用---代理
1、靜態(tài)代理(基于接口的多態(tài)性實(shí)現(xiàn)的靜態(tài)代理)
1 interface ClothFactory{ 2 void productCloth(); 3 } 4 //被代理類 5 class NikeClothFactory implements ClothFactory{ 6 @Override 7 public void productCloth(){ 8 sysytem.out.printLn("NIKE工廠生產(chǎn)一批衣服"); 9 }10 }11 //代理類12 class ProxyFactory implements ClothFactory{13 ClothFactory cf;14 public ProxyFactory(ClothFactory cf){15 this.cf = cf;16 }17 @Override18 public void productCloth(){19 sysytem.out.printLn("代理類開始執(zhí)行,收代理費(fèi)1000");20 cf.productCloth();21 }22 }23 24 public class Test{25 public static void main(String[] args){26 //① 創(chuàng)建一個(gè)被代理對象27 NikeClothFactory nike = new NikeClothFactory ();28 //② 創(chuàng)建一個(gè)代理類對象29 ProxyFactory proxy = new ProxyFactory(nike);30 //③ 調(diào)用代理類對象的方法31 proxy.productCloth();32 }33 }
靜態(tài)代理總結(jié):
① 代理類和被代理類都實(shí)現(xiàn)同一個(gè)接口
② 代理類和被代理類都實(shí)現(xiàn)接口中的方法
缺點(diǎn):每個(gè)被代理類都需要一個(gè)代理類來完成,這樣程序需要過多的代理,思考:是否能有一個(gè)萬能的代理類完成全部的代理功能?
2、動(dòng)態(tài)代理(基于反射實(shí)現(xiàn)的動(dòng)態(tài)代理)
1 interface ClothFactory{ 2 void productCloth(); 3 } 4 //被代理類 5 class NikeClothFactory inplements ClothFactory{ 6 @Override 7 public void productCloth(){ 8 sysytem.out.printLn("NIKE工廠生產(chǎn)一批衣服"); 9 }10 }11 //①必須實(shí)現(xiàn)InvocationHandler接口12 class MyInvocationHandler implements InvocationHandler{13 //② 聲明接口的代理類14 Object obj;15 //③ 創(chuàng)建一個(gè)方法實(shí)例化代理類16 public Object bind(Object obj){17 this.obj = obj;18 return Proxy.newProxyInstance(19 obj.getClass().geyClassLoder(),20 obj.getClass().getInterfaces(),this);21 }22 //④ 實(shí)現(xiàn)接口InvacationHandler的方法23 // 此方法實(shí)現(xiàn):當(dāng)調(diào)用代理類的對象方法的時(shí)候,都會(huì)轉(zhuǎn)換到它上調(diào)用24 @Override25 public Object invoke(Object proxy,Method method,Object[] args){26 Object returnVal = method.invoke(obj,args);27 return returnVal();28 }29 }30 //調(diào)用實(shí)現(xiàn)一下31 public class Test{32 public static void main(String[] args){33 //① 老規(guī)矩:創(chuàng)建一個(gè)被代理對象34 NikeClothFactory nike = new NikeClothFactory ();35 //②老規(guī)矩:創(chuàng)建一個(gè)代理類對象36 MyInvocationHandler hander = new MyinvocationHanlder();37 ClothFactory proxyCloth = (ClothFactory)hander.bind(nike);38 //③ 老規(guī)矩:調(diào)用代理類對象的方法39 proxyCloth .productCloth();40 }41 }
分類: Java
http://www.cnblogs.com/hzg110/p/6707030.html