成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java泛型:類型擦除

Hanks10100 / 1261人閱讀

博客地址:Java泛型:類型擦除

前情回顧

Java泛型:泛型類、泛型接口和泛型方法

類型擦除 代碼片段一
Class c1 = new ArrayList().getClass();
Class c2 = new ArrayList().getClass(); 
System.out.println(c1 == c2);

/* Output
true
*/

顯然在平時(shí)使用中,ArrayList()new ArrayList()是完全不同的類型,但是在這里,程序卻的的確確會(huì)輸出true。

這就是Java泛型的類型擦除造成的,因?yàn)椴还苁?b>ArrayList()還是new ArrayList(),都在編譯器被編譯器擦除成了ArrayList。那編譯器為什么要做這件事?原因也和大多數(shù)的Java讓人不爽的點(diǎn)一樣——兼容性。由于泛型并不是從Java誕生就存在的一個(gè)特性,而是等到SE5才被加入的,所以為了兼容之前并未使用泛型的類庫(kù)和代碼,不得不讓編譯器擦除掉代碼中有關(guān)于泛型類型信息的部分,這樣最后生成出來(lái)的代碼其實(shí)是『泛型無(wú)關(guān)』的,我們使用別人的代碼或者類庫(kù)時(shí)也就不需要關(guān)心對(duì)方代碼是否已經(jīng)『泛化』,反之亦然。

在編譯器層面做的這件事(擦除具體的類型信息),使得Java的泛型先天都存在一個(gè)讓人非常難受的缺點(diǎn):

在泛型代碼內(nèi)部,無(wú)法獲得任何有關(guān)泛型參數(shù)類型的信息。

代碼片段二
List list = new ArrayList();
Map map = new HashMap();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));

/* Output
[E]
[K, V]
*/

關(guān)于getTypeParameters()的解釋:

Returns an array of TypeVariable objects that represent the type variables declared by the generic declaration represented by this GenericDeclaration object, in declaration order. Returns an array of length 0 if the underlying generic declaration declares no type variables.

我們期待的是得到泛型參數(shù)的類型,但是實(shí)際上我們只得到了一堆占位符。

代碼片段三
public class Main {

    public T[] makeArray() {
        // error: Type parameter "T" cannot be instantiated directly
        return new T[5];
    }
}

我們無(wú)法在泛型內(nèi)部創(chuàng)建一個(gè)T類型的數(shù)組,原因也和之前一樣,T僅僅是個(gè)占位符,并沒(méi)有真實(shí)的類型信息,實(shí)際上,除了new表達(dá)式之外,instanceof操作和轉(zhuǎn)型(會(huì)收到警告)在泛型內(nèi)部都是無(wú)法使用的,而造成這個(gè)的原因就是之前講過(guò)的編譯器對(duì)類型信息進(jìn)行了擦除。

同時(shí),面對(duì)泛型內(nèi)部形如T var;的代碼時(shí),記得多念幾遍:它只是個(gè)Object,它只是個(gè)Object……

代碼片段四
public class Main {

    private T t;

    public void set(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    public static void main(String[] args) {
        Main m = new Main();
        m.set("findingsea");
        String s = m.get();
        System.out.println(s);
    }
}

/* Output
findingsea
*/

雖然有類型擦除的存在,使得編譯器在泛型內(nèi)部其實(shí)完全無(wú)法知道有關(guān)T的任何信息,但是編譯器可以保證重要的一點(diǎn):內(nèi)部一致性,也是我們放進(jìn)去的是什么類型的對(duì)象,取出來(lái)還是相同類型的對(duì)象,這一點(diǎn)讓Java的泛型起碼還是有用武之地的。

代碼片段四展現(xiàn)就是編譯器確保了我們放在t上的類型的確是T(即便它并不知道有關(guān)T的任何類型信息)。這種確保其實(shí)做了兩步工作:

set()處的類型檢驗(yàn)

get()處的類型轉(zhuǎn)換

這兩步工作也成為邊界動(dòng)作。

代碼片段五
public class Main {

    public List fillList(T t, int size) {
        List list = new ArrayList();
        for (int i = 0; i < size; i++) {
            list.add(t);
        }
        return list;
    }

    public static void main(String[] args) {
        Main m = new Main();
        List list = m.fillList("findingsea", 5);
        System.out.println(list.toString());
    }
}

/* Output
[findingsea, findingsea, findingsea, findingsea, findingsea]
*/

代碼片段五同樣展示的是泛型的內(nèi)部一致性。

擦除的補(bǔ)償

如上看到的,但凡是涉及到確切類型信息的操作,在泛型內(nèi)部都是無(wú)法共工作的。那是否有辦法繞過(guò)這個(gè)問(wèn)題來(lái)編程,答案就是顯示地傳遞類型標(biāo)簽。

代碼片段六
public class Main {

    public T create(Class type) {
        try {
            return type.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        Main m = new Main();
        String s = m.create(String.class);
    }
}

代碼片段六展示了一種用類型標(biāo)簽生成新對(duì)象的方法,但是這個(gè)辦法很脆弱,因?yàn)檫@種辦法要求對(duì)應(yīng)的類型必須有默認(rèn)構(gòu)造函數(shù),遇到Integer類型的時(shí)候就失敗了,而且這個(gè)錯(cuò)誤還不能在編譯器捕獲。

進(jìn)階的方法可以用限制類型的顯示工廠和模板方法設(shè)計(jì)模式來(lái)改進(jìn)這個(gè)問(wèn)題,具體可以參見(jiàn)《Java編程思想 (第4版)》P382。

代碼片段七
public class Main {

    public T[] create(Class type) {
        return (T[]) Array.newInstance(type, 10);
    }

    public static void main(String[] args) {
        Main m = new Main();
        String[] strings = m.create(String.class);
    }
}

代碼片段七展示了對(duì)泛型數(shù)組的擦除補(bǔ)償,本質(zhì)方法還是通過(guò)顯示地傳遞類型標(biāo)簽,通過(guò)Array.newInstance(type, size)來(lái)生成數(shù)組,同時(shí)也是最為推薦的在泛型內(nèi)部生成數(shù)組的方法。

以上,泛型的第二部分的結(jié)束。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64658.html

相關(guān)文章

  • Java 泛型總結(jié)(一):基本用法與類型擦除

    摘要:然而中的泛型使用了類型擦除,所以只是偽泛型??偨Y(jié)本文介紹了泛型的使用,以及類型擦除相關(guān)的問(wèn)題。一般情況下泛型的使用比較簡(jiǎn)單,但是某些情況下,尤其是自己編寫(xiě)使用泛型的類或者方法時(shí)要注意類型擦除的問(wèn)題。 簡(jiǎn)介 Java 在 1.5 引入了泛型機(jī)制,泛型本質(zhì)是參數(shù)化類型,也就是說(shuō)變量的類型是一個(gè)參數(shù),在使用時(shí)再指定為具體類型。泛型可以用于類、接口、方法,通過(guò)使用泛型可以使代碼更簡(jiǎn)單、安全。然...

    Java_oldboy 評(píng)論0 收藏0
  • Java系列之泛型

    摘要:總結(jié)泛型的類型必須是引用類型,不能是基本類型,泛型的個(gè)數(shù)可以有多個(gè),可以使用對(duì)創(chuàng)建對(duì)象時(shí)的泛型類型以及方法參數(shù)類型進(jìn)行限制,如使用關(guān)鍵字和對(duì)泛型的具體類型進(jìn)行向下限制或向上限制,最后一點(diǎn),可以聲明泛型數(shù)組,但是不能創(chuàng)建泛型數(shù)組的實(shí)例。 自從 JDK 1.5 提供了泛型概念,泛型使得開(kāi)發(fā)者可以定義較為安全的類型,不至于強(qiáng)制類型轉(zhuǎn)化時(shí)出現(xiàn)類型轉(zhuǎn)化異常,在沒(méi)有反省之前,可以通過(guò) Object...

    MadPecker 評(píng)論0 收藏0
  • 初探Java類型擦除

    摘要:可以看到,如果我們給泛型類制定了上限,泛型擦除之后就會(huì)被替換成類型的上限。相應(yīng)的,泛型類中定義的方法的類型也是如此。參考語(yǔ)言類型擦除下界通配符和的區(qū)別 本篇博客主要介紹了Java類型擦除的定義,詳細(xì)的介紹了類型擦除在Java中所出現(xiàn)的場(chǎng)景。 1. 什么是類型擦除 為了讓你們快速的對(duì)類型擦除有一個(gè)印象,首先舉一個(gè)很簡(jiǎn)單也很經(jīng)典的例子。 // 指定泛型為String List list1 ...

    DevTalking 評(píng)論0 收藏0
  • 聊聊Java泛型及實(shí)現(xiàn)

    摘要:靜態(tài)變量是被泛型類的所有實(shí)例所共享的。所以引用能完成泛型類型的檢查。對(duì)于這個(gè)類型系統(tǒng),有如下的一些規(guī)則相同類型參數(shù)的泛型類的關(guān)系取決于泛型類自身的繼承體系結(jié)構(gòu)。事實(shí)上,泛型類擴(kuò)展都不合法。 前言 和C++以模板來(lái)實(shí)現(xiàn)靜多態(tài)不同,Java基于運(yùn)行時(shí)支持選擇了泛型,兩者的實(shí)現(xiàn)原理大相庭徑。C++可以支持基本類型作為模板參數(shù),Java卻只能接受類作為泛型參數(shù);Java可以在泛型類的方法中取得...

    lewif 評(píng)論0 收藏0
  • Java泛型總結(jié)

    摘要:靜態(tài)變量是被泛型類的所有實(shí)例所共享的。對(duì)于這個(gè)類型系統(tǒng),有如下的一些規(guī)則相同類型參數(shù)的泛型類的關(guān)系取決于泛型類自身的繼承體系結(jié)構(gòu)。在代碼中避免泛型類和原始類型的混用。參考泛型類型擦除 Java泛型總結(jié) Java泛型是JDK5引入的一個(gè)新特性,允許在定義類和接口的時(shí)候使用類型參數(shù)(type parameter)。聲明的類型參數(shù)在使用的時(shí)候使用具體的類型來(lái)替換。泛型最主要的應(yīng)用是在JDK5...

    CoreDump 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<