你連存活到JDK8中著名的Bug都不知道,我怎麼敢給你加薪

公眾號:JavaEdge發表於2020-03-10

1 背景

在筆者研究 JDK 原始碼時,注意到在CopyOnWriteArrayList 和ArrayList 的構造器中都出現瞭如下 bug 字樣

6260652 其實代表的JDK bug 列表中的編號

 

上面兩個 bug 其實是同一個問題。那他到底意味著什麼呢,JDK 居然將此 bug 留在 8 了還沒處理?

看幾個例子:

2 案例

2.1 案例一

package com.javaedge;

public class Test {
    public static void main(String[] args) {
        Child[] childArray = {new Child(), new Child()};
        System.out.println(childArray.getClass());

        Father[] fatherArray = childArray;
        System.out.println(fatherArray.getClass());

        // ArrayStoreException
        fatherArray[0] = new Father();
    }
}

父類陣列中每一個元素都是子類物件,所以如下所示,這種向上轉型不會報錯

允許子類陣列轉換成父類陣列。

但陣列中元素型別都是Child型,所以如下所示,會報錯!!!



java.lang.ArrayStoreException

表明已經嘗試作出了錯誤型別的物件儲存到物件的陣列。

例如,下面的程式碼生成一個ArrayStoreException 


這意味著Object[]陣列,並不表示可以隨便將一個Object物件放進去,而取決於陣列中元素的實際型別。

2.2 案例二

List<String> list = Arrays.asList("JavaEdge"); // 返回的型別是java.util.Arrays$ArrayList,而不是ArrayList
Object[] objects = list.toArray(); // 返回String[]陣列

所以我們不能將Object物件,放到objects陣列。

2.3 案例三

 

ArrayList的toArray()返回Object[]陣列,所以可將任意物件存入 list2Array 陣列。

3 總結

通過案例二和三可以得出結論:

對於

List<String> stringList

當呼叫

Object[] objectArray = stringList.toArray()

objectArray 實際上並不一定是Object[]型別,也就不能隨便放進一個物件。

所以開頭中的原始碼都有註釋說明:

c.toArray might (incorrectly) not return Object[] (see 6260652)。

通過if判斷,避免錯誤的陣列型別儲存異常。

Arrays.copyOf(elementData, size, Object[].class)

即可確保建立得到Object[]陣列,因此可以存任意型別物件。

相關文章