Java review--反射
為什麼要使用反射?
物件在執行的時候有兩種型別:編譯時型別和執行時型別。執行時我們可能無法知道物件和類,程式只能靠執行時資訊來發現該物件和類的真實資訊,這就需要用到反射。
獲得Class物件
每個類被載入的時候,系統會為它生成一個對應的Class物件,通過Class物件,就可以訪問到JVM的這個類。Java中獲取Class物件通常採用3種方式:
1.使用Class類的forName(String clazzName)靜態方法。
2.呼叫某個類的.class屬性獲取當前的Class物件。
3.呼叫某個物件的getClass()方法。
第一種方式和第二種方式都是直接根據類來取得該類的Class物件,對比一下,第二種優勢:程式碼更安全(編譯階段可以檢查Class物件是否存在),程式效能好(不用調方法)。
從Class中獲取資訊
Class提供的功能非常豐富,它可以獲取該類包含的構造器、方法、內部類、屬性資訊等。
使用反射操作物件
物件的建立
反射生成物件有兩種方式:
1.使用Class物件的NewInstance()方法來建立類的例項。要求:類有預設構造器。
2.使用Class物件獲取指定的Constructor物件(getConstructor()方法),再呼叫Constructor物件的newInstance()方法來建立Class物件對應的例項。
呼叫方法
獲取該類對應的Class物件後,通過Class物件的getMethods()方法或者getMethod()方法來獲取全部方法。每個Method裡面有一個invoke方法Object invoke(Object obj,Object...args):obj是執行方法的主調,後面的args是執行方法時傳入方法的實參。
訪問屬性
通過Class物件的getFields()或者getField()獲取該類全部的或者指定的Field。
反射和JDK動態代理
JDK動態代理只為介面建立動態代理,下面有一個動態代理的demo:
Test.java
<span style="font-size:14px;">public class Test {
public static void main(String[] args) {
Dog target =new GunDog();
Dog dog =(Dog)MyProxyFactory.getProxy(target);
dog.info();
dog.run();
}
}
</span>
Dog.java
<span style="font-size:14px;">public interface Dog {
void info();
void run();
}
</span>
GunDog.java
<span style="font-size:14px;">public class GunDog implements Dog {
public void info(){
System.out.println("我是一個只獵狗");
}
public void run(){
System.out.println("我會跑");
}
}
</span>
MyProxyFactory.java
<span style="font-size:14px;">import java.lang.annotation.Target;
import java.lang.reflect.Proxy;
public class MyProxyFactory {
public static Object getProxy(Object target){
//建立一個MyInvokationHandler物件
MyInvocationHandler handler =new MyInvocationHandler();
handler.setTarget( target);
//建立一個動態代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
}
}
</span>
MyInvocationHandler.java
<span style="font-size:14px;">import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import org.omg.CORBA.PRIVATE_MEMBER;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target){
this.target =target;
}
//執行動態代理物件的所有方法時,都會被替代成執行如下的invoke方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
DogUtil du=new DogUtil();
//執行DogUtil 物件中的method1方法
du.method1();
//以Target為主調來執行method方法,回撥了target的原有方法
Object result=method.invoke(target, args);
du.method2();
return result;
}
}
</span>
執行結果:
Proxy和InvocationHandler就可以實現,當程式呼叫info()方法和run()方法時,系統可以自動的將method1()和method2()兩個通用方法插入info()和run()方法中執行。
MyInvocationHandler類,該實現類的invoke()方法將會作為代理物件的方法實現。
MyProxyFactory動態代理工廠類提供了一個getProxy方法, 該方法為target物件生成一個動態代理物件,這個動態代理物件與target實現了同樣的介面。當呼叫動態代理物件指定的方法的時候,實際將變成執行MyInvocationHandler物件的invoke方法。
從這個例子中可以發現,動態代理十分的靈活,代理類不僅僅可以實現被代理類要實現的介面,而且可以動態的擴充套件一些公共的方法,在原實現的前,後。
相關文章
- 【Java 反射學習】Java 反射基礎Java反射
- [Java 反射學習] Java 反射基礎Java反射
- Java反射Java反射
- Java——反射Java反射
- Java 反射Java反射
- Java反射—初探反射基礎Java反射
- Java 反射 APIJava反射API
- Java 反射原理Java反射
- 20201209——java反射Java反射
- Java的反射Java反射
- 淺析Java反射--JavaJava反射
- Java筆記-Java反射(二)Java筆記反射
- Java基礎系列—Java反射Java反射
- Java基礎 —— 反射Java反射
- Java反射機制Java反射
- [Java基礎]反射Java反射
- java反射全解Java反射
- Java 反射簡介Java反射
- java反射詳解Java反射
- Java筆記-反射Java筆記反射
- Java學習_反射Java反射
- Java 反射基礎Java反射
- Java反射-註解Java反射
- Java學習:反射Java反射
- Java反射-屬性Java反射
- Java反射-模組Java反射
- 淺析JAVA反射Java反射
- Java 反射詳解Java反射
- 秒懂Java反射Java反射
- java反射技術Java反射
- JAVA反射舉例Java反射
- Java 方法的反射Java反射
- 【Java面試指北】反射(1) 初識反射Java面試反射
- 【Java反射】Java 泛型基礎Java反射泛型
- java反射構建物件和方法的反射呼叫Java反射物件
- Java反射與hook混用反射某支付的方法Java反射Hook
- 面試題--Java反射面試題Java反射
- Java的反射機制Java反射
- Java註解和反射Java反射