Java - 泛型數(shù)組

Java不允許創(chuàng)建泛型數(shù)組的原因

上面鏈接中的Xuan Luo的回答很好. 簡單來說就是Java數(shù)組必須有一個具體的類型信息, 但是因為泛型擦除, 所以無法提供具體的類型信息給數(shù)組, 因而無法創(chuàng)建泛型數(shù)組. 而容器其實泛型擦除后根本沒類型信息了, 所以全部的List<AnyType>最后都是List. 看下面這個例子:

    public static void testTypeInformation(){
        String[] strings1 = new String[0];
        String[] strings2 = new String[0];
        Integer[] integers = new Integer[0];
        System.out.println(String.format("strings1.class == strings2.class: %s", strings1.getClass() == strings2.getClass()));
        // 直接這樣寫編譯器直接給出了錯誤
        // strings1.getClass() == integers.getClass()
        // System.out.println(String.format("strings1.class == integers.class: %s", strings1.getClass() == integers.getClass()));
        Class<?> stringArrayClass = strings1.getClass();
        Class<?> integerArrayClass = integers.getClass();
        System.out.println(String.format("strings1.class == integers.class: %s", stringArrayClass == integerArrayClass));

        // 再看容器類
        List<String> stringList = new ArrayList<>();
        List<Integer> integerList = new ArrayList<>();
        System.out.println(String.format("stringList.class == integerList.class: %s", stringList.getClass() == integerList.getClass()));

    }

輸出:

strings1.class == strings2.class: true
strings1.class == integers.class: false
stringList.class == integerList.class: true

可以看到數(shù)組是確確實實有具體類型, 而泛型容器最終都是容器class本身, 沒有新的類生成.

一些創(chuàng)建泛型數(shù)組的方法

調(diào)用反射包的方法

    /**
     * 該方法可以安全地創(chuàng)建泛型數(shù)組
     * 調(diào)用反射包里的Array.newInstance(type, length)方法.
     * 具體的實現(xiàn)是靠native方法.
     * @param type 元素類型
     * @param length 長度
     * @param <T> 類型
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] createArray(Class<T> type, int length){
        return (T[]) Array.newInstance(type, length);
    }

強制類型轉(zhuǎn)換 (錯誤方法)

    /**
     * 編譯不會報錯, 但是運行時
     * 只要T不是Object, 那一定會報錯
     * 因為Java對于數(shù)組的定義, 是必須要有具體類型的
     * 雖然 String 可以轉(zhuǎn)換為 Object, 但是Object不一定能轉(zhuǎn)換成String
     * 一樣的道理 String[] 可以轉(zhuǎn)換為 Object[], 但是Object[]不一定能
     * 轉(zhuǎn)換成String[], 另外String[]轉(zhuǎn)換為Object[]是合法的, 但是千萬
     * 不要這樣做, 很可能會出錯, 因為轉(zhuǎn)換為Object[]就能存任意引用了,
     * 但是底層仍然是String[], 如果存的不是String, 那么就會報錯.
     * @param len 長度
     * @param <T> 類型參數(shù), 可由類型推導推導得知, 也可以顯式
     *           指定, ClassName.<Type>function()
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] createArray(int len){
        return (T[]) new Object[len];
    }

測試:

        // ClassCastException
        // Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
        // 使用了類型推導
        try {
            Integer[] integers = createArray(10);
        } catch (ClassCastException e){
            System.out.println("exception: " + e.getMessage());
        }

        // 也可以這樣, 顯式指定類型
        // Integer[] integerArray = GenericArray.<Integer>createArray(10);

因為數(shù)組的實際類型是Object[], 是無法轉(zhuǎn)型為Integer[]的.

限制訪問的Object[]方法

    /**
     * 使用底層Object[]來存儲元素的折中做法
     * 不能暴露Object[]出去, 否則無法保證
     * 往里面加的類型是否安全
     * @param <T>
     */
    public static class MyArray<T>{

        // 存放實際的數(shù)據(jù)
        // 因為所有對象都能向上轉(zhuǎn)型為Object
        // 所有用Object[]來存各類對象是沒問題的
        private Object[] innerArray;

        public MyArray(int len){
            innerArray = new Object[len];
        }

        @SuppressWarnings("unchecked")
        public T get(int index){
            // 只要set方法中傳入的確實是T類型的對象
            // 那么這里一定是安全的
            return (T) innerArray[index];
        }

        public void set(int index, T item){
            innerArray[index] = item;
        }

        @Override
        public String toString() {
            return Arrays.toString(innerArray);
        }
    }

測試:

        MyArray<String> stringArray = new MyArray<>(3);
        stringArray.set(0, "The");
        stringArray.set(1, "safe");
        stringArray.set(2, "generic array");
        System.out.println(stringArray);

輸出:

[The, safe, generic array]
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姑食,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子产喉,更是在濱河造成了極大的恐慌呼渣,老刑警劉巖媒楼,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機遵倦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來官撼,“玉大人梧躺,你說我怎么就攤上這事∑缢拢” “怎么了燥狰?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斜筐。 經(jīng)常有香客問我,道長蛀缝,這世上最難降的妖魔是什么顷链? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮屈梁,結(jié)果婚禮上嗤练,老公的妹妹穿的比我還像新娘。我一直安慰自己在讶,他們只是感情好煞抬,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著构哺,像睡著了一般革答。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上曙强,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天残拐,我揣著相機與錄音,去河邊找鬼碟嘴。 笑死溪食,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的娜扇。 我是一名探鬼主播错沃,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼雀瓢!你這毒婦竟也來了枢析?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤致燥,失蹤者是張志新(化名)和其女友劉穎登疗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡辐益,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年断傲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片智政。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡认罩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出续捂,到底是詐尸還是另有隱情垦垂,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布牙瓢,位于F島的核電站劫拗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矾克。R本人自食惡果不足惜页慷,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胁附。 院中可真熱鬧酒繁,春花似錦、人聲如沸控妻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弓候。三九已至郎哭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弓叛,已是汗流浹背彰居。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撰筷,地道東北人陈惰。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像毕籽,于是被迫代替她去往敵國和親抬闯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 泛型是Java 1.5引入的新特性关筒。泛型的本質(zhì)是參數(shù)化類型溶握,這種參數(shù)類型可以用在類、變量蒸播、接口和方法的創(chuàng)建中睡榆,分別...
    何時不晚閱讀 3,038評論 0 2
  • 開發(fā)人員在使用泛型的時候萍肆,很容易根據(jù)自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數(shù)胀屿,那么如果嘗試...
    時待吾閱讀 1,055評論 0 3
  • java 泛型數(shù)組初始化 使用這樣的方式初始化java的數(shù)組會出錯塘揣,因為java不支持泛型數(shù)組。按照我的理解宿崭,ja...
    編程易行閱讀 1,554評論 0 1
  • 那天你在蔚藍的天空傲游 善良亲铡,美麗,你是如何自由 一會兒去海邊葡兑,一會兒消瘦 你看見她的眼里自己愉快的停留 然后你抱...
    小天陌塵閱讀 420評論 0 10
  • 無能奖蔓、無德、無知讹堤!
    張一德閱讀 112評論 0 0