如上面這段代碼,在靜態語言中,在編譯階段編譯器就會報錯。而對于動態語言,是可以修改變量類型的,如下面:
i = 1
i = ‘hi’
1. 先嘗試看看第一個問題,什么是反射機制?
在運行時環境,動態獲取類的信息以及動態調用對象的方法的功能,就是reflection機制。
2. 哪些地方需要反射?
* 運行時判斷任何一個對象所屬的類
* 運行時構造任何一個類的對象
* 運行時判斷任何一個類所具有的成員變量和方法
* 運行時調用任何一個對象的方法
3. 反射的使用?
先看看java reflection api, Class類是反射的入口點。有下面3種方式獲?。?/p>
1. Class.forName(“java.util.Data”)
2. T.getClass()
3. T.class
一個Class對象實際表示一個類型,但這個類型不一定是一種類。比如說int不表示類,但是int.class是一個Class類型的對象。
注:數組類型,使用getName會返回一個很奇怪的名字,如:
System.out.println(Double[].class.getName());
顯示打印的值如下:
[Ljava.lang.Double;
創建一個類的實例newInstance方法:使用默認的構造函數,沒有參數
T.class.newInstance();
Object objCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
反射分析類的能力:
4. 一個反射的簡單例子程序:
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. 當然,反射寫通用的數組代碼時,還需要用到: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;
}
動態代理部分:想清楚下面四個問題
1.什么是動態代理?
一種用于轉發請求,進行特殊處理的機制,“動態”應該指的是“運行期”。
2.為什么使用動態代理?
可以對請求進行任何處理(如事務,日志等,這都是網上說的,我當然可以做任何處理)
3.使用它有哪些好處?
如上
4.哪些地方需要動態代理?
不允許直接訪問某些類;對訪問要做特殊處理等,我只能想到這些。
1. 和動態代理有關的有兩個類
1.1 interface InvocationHandler
只這一個方法, Object invoke(Object proxy, Method method, Object[] args)
1.2 class Proxy 真正表示動態代理的類,提供兩個靜態方法:
Class> getProxyClass(ClassLoader loader, Class>[] interface)
用來產生代理類,參數要提供interface數組,它會生成這些interface的“虛擬實現”,
用來冒充真實的對象。
Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
產生代理對象,多了InvocationHandler參數(只是InvocationHandler接口的實現類),
它與代理對象關聯,當請求分發到代理對象后,會自動執行h.invoke(…)方法.
2. 動態機制的實現步驟:
/**
* 1. 實現InvocationHandler接口創建自己的調用處理器
* InvocationHandler handler = new InvocationHandlerImpl(server);
* 2. 通過Proxy指定ClassLoader對象和一組interface創建動態代理類
* Class clazz = Proxy.getProxyClass(classLoader,new class[]{…})
* 3. 通過反射機制獲取動態代理類的構造函數,其參數類型是調用處理器接口類型:
* Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class})
* 4. 通過構造函數創建動態代理類實例,將調用處理器對象作為參數被傳入
* Interface proxy = constructor.newInstance(new Object[]{handler})
*
* Proxy中newProxyInstance方法已經封裝了步驟2~4,實例如下:
*/
3. 一個簡單實用的例子:
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);
}
}
//定義一個接口協議
interface CalculatorProtocol{
public int add(int a,int b);
public int subtract(int a,int b);
}
//實現接口協議
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{
//可加入預處理
Object result = method.invoke(this.objOriginal, args);
return result;
}
}
~~EOF~~
原文地址:java反射機制及動態代理, 感謝原作者分享。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com