1. 程式人生 > >Java 為什麼不能建立泛型陣列?

Java 為什麼不能建立泛型陣列?

泛型是 JDK 1.5 中引入的新特性, 首先我們來思考下 java 為什麼要引入泛型, 我們看如下程式碼:

        List list = new ArrayList();
        list.add(55);
        list.add("dd");
        System.out.println(((Integer) list.get(1)) - 5);

這段程式碼在編譯器是沒有任何問題的, 可以通過編譯, 但是執行時會得到 java.lang.ClassCastException 異常, 如果使用泛型的話,

        List<Integer> list = new ArrayList<>();
        list.add(55);
        list.add("dd"); // 編譯錯誤
        System.out.println(((Integer) list.get(1)) - 5);

到這裡我們明白了:

 java 之所以引入泛型是為了增強程式的安全性和正確性, 以便在編譯期就能檢查出型別相關的錯誤.

那麼既然這樣, 為什麼不能使用泛型陣列呢?  首先假設如果可以使用泛型陣列, 我們看下面一段程式碼:

        List<Integer>[] list = new ArrayList<Integer>[10]; // 泛型陣列
        Object[] objects = list;

        List<String> stringList = new ArrayList<>();
        stringList.add("dd");

        objects[0] = stringList;

        Integer s = ((List<Integer>) objects[0]).get(0);
        System.out.println(s);

如果可以使用泛型陣列, 這段程式碼在編譯期間沒有任何問題, 但是在執行期又會出現煩人的 java.lang.ClassCastException , 我們來分析下為什麼:

  1. 首先我們知道, java中的陣列是可以向上轉型成基類的陣列的, 這個不用多說, java中的引用多型的機制.
  2. 然後我們知道 java 中的泛型實現的原理是型別擦除, 因此我們上面定義的 list<Integer> 和 list<String> 都會被擦除成 list<Object>, 所以我們可以在 objects 中加入 list<string> 這種型別的引用.
  3. 當我們加入 list<string> 這種型別的引用後, 如果我們按照原來定義泛型陣列時使用的 list<integet> 型別來訪問陣列中的元素的話固然又會引入 java.lang.ClassCastException.

綜上所述, 可以用一句話來描述 java 為什麼不能建立泛型陣列:

使用泛型的作用是使得程式在編譯期可以檢查出與型別相關的錯誤,但是如果使用了泛型陣列,這種能力就會受到破壞.

參考博文: