如上面這段代碼,在靜態(tài)語言中,在編譯階段編譯器就會(huì)報(bào)錯(cuò)。而對(duì)于動(dòng)態(tài)語言,是可以修改變量類型的,如下面:
i = 1
i = ‘hi’
1. 先嘗試看看第一個(gè)問題,什么是反射機(jī)制?
在運(yùn)行時(shí)環(huán)境,動(dòng)態(tài)獲取類的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能,就是reflection機(jī)制。
2. 哪些地方需要反射?
* 運(yùn)行時(shí)判斷任何一個(gè)對(duì)象所屬的類
* 運(yùn)行時(shí)構(gòu)造任何一個(gè)類的對(duì)象
* 運(yùn)行時(shí)判斷任何一個(gè)類所具有的成員變量和方法
* 運(yùn)行時(shí)調(diào)用任何一個(gè)對(duì)象的方法
3. 反射的使用?
先看看java reflection api, Class類是反射的入口點(diǎn)。有下面3種方式獲取:
1. Class.forName(“java.util.Data”)
2. T.getClass()
3. T.class
一個(gè)Class對(duì)象實(shí)際表示一個(gè)類型,但這個(gè)類型不一定是一種類。比如說int不表示類,但是int.class是一個(gè)Class類型的對(duì)象。
注:數(shù)組類型,使用getName會(huì)返回一個(gè)很奇怪的名字,如:
System.out.println(Double[].class.getName());
顯示打印的值如下:
[Ljava.lang.Double;
創(chuàng)建一個(gè)類的實(shí)例newInstance方法:使用默認(rèn)的構(gòu)造函數(shù),沒有參數(shù)
T.class.newInstance();
Object objCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
反射分析類的能力:
4. 一個(gè)反射的簡(jiǎn)單例子程序:
package com.lifeware.study.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectTetser {
public Object copy(Object obj) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{
Class> classType = obj.getClass();
System.out.println(classType.getName());
Object objCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
Field[] fields = classType.getDeclaredFields();
for(Field field:fields){
System.out.println(field.getName());
String firstLetter = field.getName().substring(0,1).toUpperCase();
String getMethodName = “get” + firstLetter + field.getName().substring(1);
String setMethodName = “set” + firstLetter + field.getName().substring(1);
Method getMethod = classType.getMethod(getMethodName, new Class[]{});
Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()});
Object value = getMethod.invoke(obj, new Object[]{});
setMethod.invoke(objCopy, new Object[]{value});
}
return objCopy;
}
/**
* @param args
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
// TODO Auto-generated method stub
Customer cus = new Customer();
cus.setId(new Long(100));
cus.setAge(new Long(50));
cus.setName(“zhangsan”);
Customer cuscopy = (Customer) new ReflectTetser().copy(cus);
System.out.println(cuscopy.getId() + “,” + cuscopy.getAge() + “,” + cuscopy.getName());
}
}
class Customer{
private Long id;
private Long age;
private String name;
public Customer(){
}
public Long getId(){
return id;
}
public Long getAge(){
return age;
}
public String getName(){
return name;
}
public void setId(Long id){
this.id = id;
}
public void setAge(Long age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
5. 當(dāng)然,反射寫通用的數(shù)組代碼時(shí),還需要用到:java.lang.reflect.Array
public static Object goodArrayGrow(Object a){
Class> c1 = a.getClass();
if(!c1.isArray()){
return null;
}
Class> componentType = c1.getComponentType();
int length = Array.getLength(a);
int newLength = length * 11/10 + 10;
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(a, 0, newArray, 0, length);
return newArray;
}
動(dòng)態(tài)代理部分:想清楚下面四個(gè)問題
1.什么是動(dòng)態(tài)代理?
一種用于轉(zhuǎn)發(fā)請(qǐng)求,進(jìn)行特殊處理的機(jī)制,“動(dòng)態(tài)”應(yīng)該指的是“運(yùn)行期”。
2.為什么使用動(dòng)態(tài)代理?
可以對(duì)請(qǐng)求進(jìn)行任何處理(如事務(wù),日志等,這都是網(wǎng)上說的,我當(dāng)然可以做任何處理)
3.使用它有哪些好處?
如上
4.哪些地方需要?jiǎng)討B(tài)代理?
不允許直接訪問某些類;對(duì)訪問要做特殊處理等,我只能想到這些。
1. 和動(dòng)態(tài)代理有關(guān)的有兩個(gè)類
1.1 interface InvocationHandler
只這一個(gè)方法, Object invoke(Object proxy, Method method, Object[] args)
1.2 class Proxy 真正表示動(dòng)態(tài)代理的類,提供兩個(gè)靜態(tài)方法:
Class> getProxyClass(ClassLoader loader, Class>[] interface)
用來產(chǎn)生代理類,參數(shù)要提供interface數(shù)組,它會(huì)生成這些interface的“虛擬實(shí)現(xiàn)”,
用來冒充真實(shí)的對(duì)象。
Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
產(chǎn)生代理對(duì)象,多了InvocationHandler參數(shù)(只是InvocationHandler接口的實(shí)現(xiàn)類),
它與代理對(duì)象關(guān)聯(lián),當(dāng)請(qǐng)求分發(fā)到代理對(duì)象后,會(huì)自動(dòng)執(zhí)行h.invoke(…)方法.
2. 動(dòng)態(tài)機(jī)制的實(shí)現(xiàn)步驟:
/**
* 1. 實(shí)現(xiàn)InvocationHandler接口創(chuàng)建自己的調(diào)用處理器
* InvocationHandler handler = new InvocationHandlerImpl(server);
* 2. 通過Proxy指定ClassLoader對(duì)象和一組interface創(chuàng)建動(dòng)態(tài)代理類
* Class clazz = Proxy.getProxyClass(classLoader,new class[]{…})
* 3. 通過反射機(jī)制獲取動(dòng)態(tài)代理類的構(gòu)造函數(shù),其參數(shù)類型是調(diào)用處理器接口類型:
* Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class})
* 4. 通過構(gòu)造函數(shù)創(chuàng)建動(dòng)態(tài)代理類實(shí)例,將調(diào)用處理器對(duì)象作為參數(shù)被傳入
* Interface proxy = constructor.newInstance(new Object[]{handler})
*
* Proxy中newProxyInstance方法已經(jīng)封裝了步驟2~4,實(shí)例如下:
*/
3. 一個(gè)簡(jiǎn)單實(shí)用的例子:
package com.lifeware.study.reflection;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
CalculatorProtocol server = new Server();
InvocationHandler handler = new CalculatorHandler(server);
CalculatorProtocol client = (CalculatorProtocol)Proxy.newProxyInstance(server.getClass().getClassLoader(),
server.getClass().getInterfaces(), handler);
int result = client.add(3, 2);
System.out.println(“3+2=” + result);
result = client.subtract(5, 2);
System.out.println(“5-2=” + result);
}
}
//定義一個(gè)接口協(xié)議
interface CalculatorProtocol{
public int add(int a,int b);
public int subtract(int a,int b);
}
//實(shí)現(xiàn)接口協(xié)議
class Server implements CalculatorProtocol{
public int add(int a,int b){
return a+b;
}
public int subtract(int a,int b){
return a-b;
}
}
class CalculatorHandler implements InvocationHandler{
private Object objOriginal;
public CalculatorHandler(Object obj){
this.objOriginal = obj;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
//可加入預(yù)處理
Object result = method.invoke(this.objOriginal, args);
return result;
}
}
~~EOF~~
原文地址:java反射機(jī)制及動(dòng)態(tài)代理, 感謝原作者分享。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com