Java泛型的一些限制

來源:互聯網
上載者:User

標籤:泛型   java   

    本文主要參考《Java編程思想(第4版)》的Java泛型章節,僅當一個簡單的讀書筆記。

    和C++泛型對比,Java泛型只是一種編譯期間的擦拭機制。這是由於考慮到和以前的相容而考慮的一種折中方案。在編譯好的泛型代碼裡,編譯期間已經把所有的泛型資訊給擦拭掉,因此無法獲得任何有關泛型參數類型的資訊。因此List<String>和List<Integer>實際上是同一類型。

    參考以下代碼:

    //以下3個例子都無法通過編譯    public <T> void testGeneric(Object arg) {        if (arg instanceof T) {}    //1        T var = new T();             //2        T[] array = new T[100]; //3    }

    從以上代碼可以看到,這種擦拭機制的限制包括如下:

1、instanceof無法使用

2、無法執行個體化泛型類

3、無法執行個體化泛型數組

    以上3種方法無法通過編譯的主要原因是,泛型的擦拭機制把具體的類型資訊都擦拭,無法在運行時知道確切的類型資訊。不過Java提供了另外的方法去繞過這些限制。

解決1

對於第1種,無法使用instanceof文法,我們可以利用動態isInstance():

    //testInstance(String.class, "abc") == true    public static <T> boolean testInstance(Class<T> c, Object arg) {        return c.isInstance(arg);    }<
解決2 

    對於第2種,無法執行個體化泛型類,如果對於要執行個體化的泛型類,擁有無參預設建構函式,我們可以利用Class對象:

    public static <T> T createGeneric(Class<T> c) {        T x = null;        try {            x = c.newInstance();        } catch (Exception e) {            throw new RuntimeException(e); //createGeneric<Integer.class>會拋出異常,由於Integer沒有預設建構函式        }        return x;     }
    由於以上代碼採用Class對象執行個體化擁有一定限制,因此我們還可以藉助Factory 方法,顯示建立對應的類:

    interface GenericFactory<T> {        T create();    }        class IntegerFactory implements GenericFactory<Integer> {        @Override        public Integer create() {            return new Integer(0);        }    }
解決3

對於第3種,無法執行個體化泛型數組,我們可以藉助ArrayList<T>來代替,但如果一定要獲得數組的行為,以及泛型提供的編譯期的安全類型,

    //GenericArray ga = new GenericArray<Integer>(10);    //ga.put(3, 10);    //int abc = (Integer) ga.get(3);    //Integer[] aaa = (Integer[]) ga.array(); //拋出ClassCastException    class GenericArrayEx<T> {        private T[] array;        public GenericArray(int size) {            array = (T[]) new Object[size];        }        public void put(int index, T item) {            array[index] = item;        }        public T get(int index) {            return array[index];        }        public T[] array() {            return array;        }    }
    對於以上代碼,我們採用一個GenericArray的類進行封裝,但內部實際還是一個Object[]的對象數組,在put和get的時候獲得了編譯期間的檢查,但問題來了,如果我們使用array()方法企圖獲得內部數組並轉型的時候,會拋出ClassCastException,這是由於數組實際還是Object[]對象!為瞭解決這個問題,我們可以使用Array.newInstance。

    //GenericArrayEx ga = new GenericArrayEx<Integer>(Integer.class, 10);    //ga.put(3, 10);    //int abc = (Integer) ga.get(3);    //Integer[] aaa = (Integer[]) ga.array(); //可以成功轉型    class GenericArrayEx<T> {        private T[] array;        public GenericArrayEx(Class<T> type, int size) {            array = (T[]) Array.newInstance(type, size);        }        public void put(int index, T item) {            array[index] = item;        }        public T get(int index) {            return array[index];        }        public T[] array() {            return array;        }    }
    這樣,就可以使用T[]了。


Java泛型的一些限制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.