[英]Why does adding an Integer to a String array in Java not generate a compilation error?
為什么我嘗試將Integer
添加到聲明為Object[]
但實例化為String[]
的Java數組時,不會產生編譯錯誤?
Object[] ob = new String[1];
ob[0] = new Integer(1); // this shouldn’t compile but it does!
當我運行它時,我得到了一個運行時異常,而不是(更受歡迎的)編譯時錯誤! 這是正確的行為嗎? 我是否應該收到編譯時錯誤?
Java設計人員已經做出了選擇: String[]
擴展了Object[]
,但是您不能在未獲取運行時異常的情況下向其具體類型為String[]
的數組添加除String
之外的任何內容。
他們可能使無效的內容如下:
Object[] ob = new String[1];
因為它有效地允許將任何類型的對象添加到數組而不會出現任何編譯器錯誤(如您所注意到的),這很正常,因為Integer 是 Object,並且數組的編譯時類型是Object[]
。
他們沒有為數組選擇此選項,但為通用集合做了選擇:
List<Object> ob = new ArrayList<String>();
生成編譯器錯誤,因為List<String>
不擴展List<Object>
。 通常,集合比數組更可取,因為它們更安全,並且提供了更多功能。
您可能要考慮的要點是引用數組的運行時類型( String[]
)與數組變量的編譯時類型( Object[]
)。 編譯器僅強制您放入數組中的內容與引用該數組變量的靜態類型兼容。 這個例子使它脫穎而出:
String[] strs = new String[1];
Object[] objs = strs;
strs[0] = new Integer(1); /* error, says the compiler! */
objs[0] = new Integer(1); /* fine by me, says the compiler! */
現在,您應該理所當然地感到煩惱的是您的第一行: Object[] ob = new String[1];
這意味着String[]
與Object[]
String[]
是賦值兼容的,換句話說,它是其子類型。 這與CS眾所周知的事實相反,即容器類型在其元素的類型中是相反的。 為什么用Java卻不是呢? 我曾經讀過一個關於James Gosling的詢問的信,他回答說他們知道事實,但是希望Java方法能夠以一種簡單的方式(通過Object[]
類型)接受任何類型的數組。 這源於對Java的要求,即它必須是“藍領語言”,並且不能陷入類型理論上的精確性,而這些精確性會帶來自己的心理負擔。 見證仿制葯<? super String>
<? super String>
和Scala的協變/反變位置規則。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.