java反射的常見方式
反射常用于DI(依賴注入)的框架,如:Spring,guice等,在程序啟動時這些框架讀取配置文件中定義的類名然后根據類名去實例化類。
Class<?> c=Class.forName("com.younchen.model.Student");
Student s=(Student) c.newInstance();
反射的方式常見的有 :傳統的反射方式(上面的例子),代理方式 , 方法句柄 ,以下是三種的基本實現。
以調用一個類的私有方法為例:
Person類:
package com.younchen.ioc;
public class People {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void getMoney(String money){
System.out.println("reciveMoney :"+money);
}
}
Manager類:
package com.younchen.ioc;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
public class Manager {
// 通過反射方法執行
public Method getReflectMethod() {
Class<?>[] params = new Class[] { People.class, String.class };
Method method = null;
try {
method = Manager.class.getDeclaredMethod("giveMoney", params);
// 私有方法訪問權限
method.setAccessible(true);
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return method;
}
// 通過方法句柄執行
public MethodHandle getMethodHandler() {
MethodType mt = MethodType.methodType(void.class, People.class,
String.class);
MethodHandle mh = null;
try {
mh = MethodHandles.lookup().findVirtual(Manager.class, "giveMoney",
mt);
} catch (Exception ex) {
ex.printStackTrace();
}
return mh;
}
// 代理方式
public static class ProxyPerson {
private ProxyPerson() {
};
public static ProxyPerson makeProxy() {
return new ProxyPerson();
}
public void invoke(Manager manager, People people, String food) {
manager.giveMoney(people, food);
}
}
/**
* 要執行的私有方法
*/
private void giveMoney(People people, String money) {
people.getMoney(money);
}
}
測試類:
package com.younchen.ioc;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMain {
Manager manager=new Manager();
People people=new People();
String money="100$";
public void sendmoney(){
//sendByHandleMethod();
//sendByProxy();
sendByReflect();
}
public void sendByProxy(){
System.out.println("通過代理執行");
Manager.ProxyPerson.makeProxy().invoke(manager,people,money );
}
public void sendByReflect(){
try {
System.out.println("通過反射執行");
Method mh= manager.getReflectMethod();
mh.invoke(manager,people,money);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendByHandleMethod(){
try {
System.out.println("通過方法句柄執行");
manager.getMethodHandler().invokeExact(manager,people,money);
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
TestMain t=new TestMain();
t.sendmoney();
}
}
方法句柄的優勢:
1.相比傳統的反射方式方法句柄更加簡潔,可維護性好。
2.跟方法句柄在恰當的上下文中對所有的方法都有訪問權限,跟安全管理器沒有沖突,而且與代理模式比起來,方法句柄方式不占用PermGen,因為代理模式需要保存要引用的類有時可能需要較多的PermGen.
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!