學會Java泛型系列(四):擦除帶來的問題以及解決辦法

擦除帶來的問題

擦除主要的正當理由是從非泛化代碼到泛化代碼的轉(zhuǎn)變過程,以及在不破壞現(xiàn)有類庫的情況下,將泛型融入Java中。

1.泛型不能用于顯式地引用運行時類型的操作之中,例如instanceof、new

class Erased<T>{

    public void f(T t,String a){
        //T t = new T(); //error
        //T[] ts = new T[100]; //error
        //boolean k = a instanceof T; //error
    }
}

我們可以把具體類型的Class傳進來解決部分問題

class Erased<T>{

    Class<T> kind;
    
    public Erased(Class<T> kind){
        this.kind = kind;
    }
    
    public void f(String a) throws Exception{
        T t = kind.newInstance(); //這個類需要有默認構(gòu)造器,反射知識
        T[] ts = (T[]) Array.newInstance(kind,10);
        boolean k = kind.isInstance(a);
    }
}

2.基本類型不能作為參數(shù)類型

由于擦除的原因,類型參數(shù)會被擦除到上一邊界,邊界是一個類,不兼容基本類型,所以不能聲明List<int>。

Java1.5后有自動包裝機制,可以用List<Integer>實現(xiàn)基本類型的泛化。但是要注意int[]與Integer[]是轉(zhuǎn)化的,在一些需要傳Integer[]的地方不能傳int[].

3.數(shù)組

可以聲明帶泛型的數(shù)組引用,但是不能直接創(chuàng)建帶泛型的數(shù)組對象

    List<String>[] stringLists; //可以聲明帶泛型的數(shù)組引用
    List<String>[] stringLists2 = new ArrayList<String>[1];//不能直接創(chuàng)建帶泛型的數(shù)組對象
    List<String>[] stringLists3 = new ArrayList[1];

可以通過Array.newInstance(Class<T>,int)來創(chuàng)建T[]

4.重載

class Holder<T,E>{
    void f(List<T> list){}
    void f(List<E> list){}
}

上面的代碼將會編譯不通過,由于擦除的原因,這兩個方法的類型簽名是一樣的。

5.基類劫持了接口

interface Run<T>{
    void with(T t);
}

class Animal implements Run<Integer>{

    @Override
    public void with(Integer integer) {}
}

public class Dog extends Animal implements Run<String>{}//報錯

子類與父類繼承用一個泛型接口,如果兩個泛型類型不同,將會被父類類型劫持

目錄

學會Java泛型系列(零):簡介及目錄
學會Java泛型系列(一):Java泛型
學會Java泛型系列(二):泛型定義與使用
學會Java泛型系列(三):泛型原理-擦除
學會Java泛型系列(四):擦除帶來的問題以及解決辦法
學會Java泛型系列(五):限定符
學會Java泛型系列(六):總結(jié)
學會Java泛型系列(七):常用案例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容