描述
理解
題目中的這段程序在編譯器正常,運行時異常。錯誤出現在 b[1] = Integer.valueOf(42);
這一行代碼, a
賦值給 b
,a
和 b
指向同一對象 new String[2]
,而 String[]
的實現是不支持 set integer
操作。
這行引發運行時異常。從實現角度來說,Java的數組是協變的:也就說Java的類型系統認爲子類數組可以被賦值給父類數組。而這種賦值和對象的多態類似,它並不會實際改變數組元素的實際類型,於是乎在上述的例子中儘管b表面上是Object[]類型,但是運行時它的實際類型是String[],內部元素也只能添加字符串(因爲Java的數組不同與泛型,數組是存在運行時類型檢查的),於是就引發了這種現象:編譯期編譯通過(因爲表面的類型檢查認爲沒有什麼問題),運行時拋出異常(把事實上的Integer對象存進了String數組)。
作者:陸萌萌
鏈接:https://www.zhihu.com/question/371957442/answer/1017620831
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
如果想要編譯時報錯,我們可以用 List
代替 Array
:
public class TestJava {
public static void f() {
String[] a = new String[2];
Object[] b = a;
a[0] = "hi";
b[1] = Integer.valueOf(42); // 此處運行時異常
System.out.println(a);
System.out.println(b);
}
public static void o() {
List<String> a = new ArrayList<>(2);
List<Object> b = a; // 此處類型檢查時會報錯
a.set(0, "hi");
b.set(1, Integer.valueOf(42));
}
public static void main(String[] args) {
f();
}
}
參考:
一道 Java 面試題:https://www.yinwang.org/blog-cn/2020/02/13/java-type-system
知乎討論:https://www.zhihu.com/question/371957442