Java多態與反射


多態經過分離作什麼和怎麼作,從另外一個角度將接口與實現分離開來;經過多態來消除類型之間的耦合關係,在Java中,多態也叫動態綁定,後期綁定或運行時綁定,那麼什麼是方法綁定?java

方法調用綁定:

將一個方法與調用同一個方法的主體關聯起來被稱爲綁定;若在程序執行前進行綁定(由編譯器和鏈接程序實現),叫作前期綁定;還有一種叫後期綁定,就是在運行時根據對象的類型進行綁定,也叫動態綁定或運行時綁定,也就是說,編譯器不知道對象的類型,可是方法調用機制能找到正確的方法體;在Java中除了static方法和final方法以外,全部的其餘方法都是後期綁定;編程

所以,Java中全部的方法都是經過動態綁定來實現多態的,但若是直接訪問某個域,則這個訪問就會在編譯其進行解析;通常咱們都經過將子類向上轉型爲父類來實現多態,父類能夠是抽象類,只要子類實現到父類的全部抽象方法,就能夠將子類轉型爲抽象的父類;Java裏的抽象類自己是不能被實例化,但能夠將子類的引用向上轉型爲抽象的父類。
如:ide

abstract class Jack{
        public abstract void doSomething();
    }
class Product extends Jack{

        @Override
        public void doSomething() {
            System.out.println("Product");
            
        }
        
    }
    public static void main(String[] args) {
    //聲明一個抽象類Jack的變量,並指向其子類的實例化對象,合法的,Java的多態性會保證在運行時能夠獲得其正確的類型;
        Jack jack=new Product();
        //Jack jack=new Jack();//非法,不能實例化抽象類對象
        jack.doSomething();
    }

Java反射

Java反射機制是指在運行狀態時,能夠知道任意一個類的的全部屬性和方法,對任意一個對象均可以調用它的任意一個方法;經過反射,能夠在運行時實例化對象函數

Java反射提供的功能包括:this

  • 在運行時判斷一個對象所屬的類;
  • 運行時構造任意一個類的對象;
  • 運行時判斷任意一個類的成員變量與方法;
  • 運行時調用任意一個對象的方法;
  • 生成動態代理;

咱們想獲得一個類的全部信息,第一步就是要獲得類的Class對象,若是知道了一個對象或類的名字,就能夠經過簡單的:
Class<?> clz=對象.getClass();
Class<?> clz=類的名字.class
獲得,但若是在編譯期得不到具體類型,則能夠經過Class.forName()來獲得,但這個方法生成的結果在編譯時是不可知的,全部的方法特徵簽名都是在運行時提取出來的。這是由Java的反射機制來提供足夠的支持。在獲得這個類的Class對象後,咱們就能夠反射來構造對象,進而獲得這個類的全部的信息。代理

public static Class<?> forName(String className)
                throws ClassNotFoundException {
         Class<?> caller = Reflection.getCallerClass();
         return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

Java裏的Class類與java.lang.reflect類庫一塊兒對反射進行支持,該類庫包含了Field,Method,Constructor類(每一個類都實現了Member接口),這些類型的對象是在JVM在運行時建立的,用以表示未知類裏對應的成員。這樣咱們就可使用Constructor建立新的對象,用get(),set()方法修改與Field對象關聯的字段,用invoke()方法調用與Method對象關聯的方法。(摘自《Java編程思想》第四版)code

下面簡要介紹利用反射實現的動態代理;對象

動態代理

步驟:接口

  • 新建委託類,實現動態代理要求委託類必須實現某個接口;
  • 新建中間類,用來鏈接代理類和委託類,這個中間必須實現InvocationHandler接口,這個接口只有一個invoke()方法;
  • 經過Proxy類新建代理類對象;

舉例:開發

interface Operate{
        void method1();
        void method2();
        void method3();
    }
    /**
     * 委託類
     * @author wood
     *
     */
    class Entrust implements Operate{

        @Override
        public void method1() {
            // TODO Auto-generated method stub
            System.out.println("*method1");
        }

        @Override
        public void method2() {
            // TODO Auto-generated method stub
            System.out.println("*method2");
        }

        @Override
        public void method3() {
            // TODO Auto-generated method stub
            System.out.println("*method3");
        }
        
    }
    /**
     * 鏈接委託類與代理類的中間類;
     * @author wood
     *
     */
    class DynamecProxyHandler implements InvocationHandler{
        private Object proxied;//委託類對象
        public DynamecProxyHandler(){
            
        }
        public DynamecProxyHandler(Object object){
            this.proxied=object;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] arg2)
                throws Throwable {
            // TODO Auto-generated method stub
            Object 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 動態代理

相關文章
相關標籤/搜索