Exception in thread "main" java.lang.ClassCastException: $Proxy0 利用匿名內部類創建InvocationHandler接口實現

這裏錯誤的描述大致爲:不能將動態代理的返回對象強轉爲對應的類!
對於這個錯誤,最終原因還是沒弄清楚,但是最後發現了錯誤的根源,再次跟大家分享一下!先貼出整個創建動態代理類需要的類以及接口。值得注意的是,這裏介紹的是實現接口的類的動態代理,沒有實現接口的動態代理怎麼實現,參照高手的博客。
1、Caculate.java接口

package com.lds.util;

public interface Calculate {
    public int add(int i, int j);
    public int sub(int i, int j);
    public int mul(int i, int j);
    public float div(int i, int j);
}

2、Caculate接口的實現類CaculateImp.java

package com.lds.util;

public class CalculateImp implements Calculate {

    @Override
    public int add(int i, int j) {

        int result = i + j;
        return result;
    }

    @Override
    public int sub(int i, int j) {

        int result = i - j;
        return result;
    }

    @Override
    public int mul(int i, int j) {

        int result = i * j;
        return result;

    }

    @Override
    public float div(int i, int j) {

        float result = (float) i / j;
        return result;

    }

}

3、創建動態代理的實例對象

package com.lds.util;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest {

    public static void main(String args[]) {

        final CalculateImp target = new CalculateImp();
        Calculate proxy = (Calculate) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method 
      method,Object[] args) throws Throwable {
        System.out.println("Before method excute ");
        Object result = method.invoke(target, args);
        System.out.println(result);
        System.out.println("After Method excute " + "\n");
        return result;
        }
});

        proxy.add(1, 2);
        proxy.sub(4, 3);
        proxy.mul(2, 2);
        proxy.div(3, 2);

    }

}

後來發現出錯的地方就是這裏:
Calculate proxy = (Calculate) Proxy.newProxyInstance
在上面的強轉中,強轉類型不能寫成Calculate接口的實現類CalculateImp,而只能寫成接口類型,否則會報上面的錯;之前檢查錯誤,從來沒想到這個問題,後來仔細想想,轉成接口類型,應該是很有道理的,而不能轉成接口實現類類型。
因爲對於Calculate接口,可以被任何類實現,實現之後的類型仍然可以寫成接口類型,在java中會自動進行轉換成對應的實現類類型。這樣的例子比如:

List<?> list = new ArrayList<?>(); 

看到這裏的List類型也就應該明白了,當然這個List可以換成ArrayList。

ArrayList<Integer> list = new ArrayList<Integer>(); 

從上面的實例也可以看出來,創建代理類後,實現類CalculateImp中的方法與InvocationHandler的實現類中的invoke()方法的執行順序,是先執行invoke()方法。
上述的一點心得僅代表個人觀點,或許有不對的地方,希望各位大蝦可以指正,互相學習進步。

發佈了20 篇原創文章 · 獲贊 5 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章