Java多态与反射
多態通過分離做什么和怎么做,從另一個角度將接口與實現分離開來;通過多態來消除類型之間的耦合關系,在Java中,多態也叫動態綁定,后期綁定或運行時綁定,那么什么是方法綁定?
方法調用綁定:
將一個方法與調用同一個方法的主體關聯起來被稱為綁定;若在程序執行前進行綁定(由編譯器和連接程序實現),叫做前期綁定;還有一種叫后期綁定,就是在運行時根據對象的類型進行綁定,也叫動態綁定或運行時綁定,也就是說,編譯器不知道對象的類型,但是方法調用機制能找到正確的方法體;在Java中除了static方法和final方法之外,所有的其他方法都是后期綁定;
因此,Java中所有的方法都是通過動態綁定來實現多態的,但如果直接訪問某個域,則這個訪問就會在編譯其進行解析;一般我們都通過將子類向上轉型為父類來實現多態,父類可以是抽象類,只要子類實現到父類的所有抽象方法,就可以將子類轉型為抽象的父類;Java里的抽象類本身是不能被實例化,但可以將子類的引用向上轉型為抽象的父類。
如:
Java反射
Java反射機制是指在運行狀態時,可以知道任意一個類的的所有屬性和方法,對任意一個對象都可以調用它的任意一個方法;通過反射,可以在運行時實例化對象
Java反射提供的功能包括:
- 在運行時判斷一個對象所屬的類;
- 運行時構造任意一個類的對象;
- 運行時判斷任意一個類的成員變量與方法;
- 運行時調用任意一個對象的方法;
- 生成動態代理;
我們想得到一個類的所有信息,第一步就是要得到類的Class對象,如果知道了一個對象或類的名字,就可以通過簡單的:
Class<?> clz=對象.getClass();
Class<?> clz=類的名字.class
得到,但如果在編譯期得不到具體類型,則可以通過Class.forName()來得到,但這個方法生成的結果在編譯時是不可知的,所有的方法特征簽名都是在運行時提取出來的。這是由Java的反射機制來提供足夠的支持。在得到這個類的Class對象后,我們就可以反射來構造對象,進而得到這個類的所有的信息。
Java里的Class類與java.lang.reflect類庫一起對反射進行支持,該類庫包含了Field,Method,Constructor類(每個類都實現了Member接口),這些類型的對象是在JVM在運行時創建的,用以表示未知類里對應的成員。這樣我們就可以使用Constructor創建新的對象,用get(),set()方法修改與Field對象關聯的字段,用invoke()方法調用與Method對象關聯的方法。(摘自《Java編程思想》第四版)
下面簡要介紹利用反射實現的動態代理;
動態代理
步驟:
- 新建委托類,實現動態代理要求委托類必須實現某個接口;
- 新建中間類,用來連接代理類和委托類,這個中間必須實現InvocationHandler接口,這個接口只有一個invoke()方法;
- 通過Proxy類新建代理類對象;
舉例:
interface Operate{void method1();void method2();void method3();}/*** 委托類* @author wood**/class Entrust implements Operate{@Overridepublic void method1() {// TODO Auto-generated method stubSystem.out.println("*method1");}@Overridepublic void method2() {// TODO Auto-generated method stubSystem.out.println("*method2");}@Overridepublic void method3() {// TODO Auto-generated method stubSystem.out.println("*method3");}}/*** 連接委托類與代理類的中間類;* @author wood**/class DynamecProxyHandler implements InvocationHandler{private Object proxied;//委托類對象public DynamecProxyHandler(){}public DynamecProxyHandler(Object object){this.proxied=object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] arg2)throws Throwable {// TODO Auto-generated method stubObject object=method.invoke(proxied, arg2);System.out.println(method.getName());return object;}}//***********************DynamecProxyHandler dymaProxy=new DynamecProxyHandler(new Entrust());//通過Proxy類的靜態函數生成代理對象;Operate operate=(Operate)Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[]{Operate.class}, dymaProxy);operate.method1();operate.method2();operate.method3();我們通過Procy.newProcyInstance函數新建了一個代理對象,實際的代理類就是在這時候動態生成了,我們調用該代理對象的函數就會調用到中間類的invoke函數,而invoke函數實現調用委托類的對應函數;
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader是類加載器;
interfaces是委托類的接口,生成代理需要實現這個接口;
實際上Java的動態代理就是兩層的靜態代理:開發者提供一個委托類A,程序動態生成了一個代理類B,開發者還需要提供一個實現了InvocationHandler的接口C,用類C來連接委托類A和委托類B,類C是代理類B的委托類,是類A的代理類;用戶直接調用代理類B,B將調用轉發給委托類C,C再將調用轉發給委托類A;
參考:
《Java編程思想》第四版
公共技術點之 Java 動態代理
轉載于:https://www.cnblogs.com/WoodJim/p/4722107.html
總結
- 上一篇: 681_python安装win32com
- 下一篇: Commit Monitor–svn监控