簡體   English   中英

為什么在 Java 泛型右側的集合類型沒有任何影響?

[英]Why in Java generics right hand side type of the collection does not have any effect?

使用 Java 的泛型特性,我創建了一個 List 對象,在左側我使用原始類型 List,而在右側我使用泛型類型 ArrayList<String>。

List myList=new ArrayList<String>();

我在列表對象中添加了一個 int 值。

myList.add(101);

我希望我會得到一些編譯錯誤,但這個程序運行良好。但是如果我在左側使用泛型類型 List< String > 並在右側使用原始類型 ArrayList 並嘗試將一個 int 值添加到列表,我按預期收到編譯錯誤。

List<String> myList=new ArrayList();
myList.add(101);//The method add(int, String) in the type List<String> is not applicable for the arguments (int)

為什么在 Java 泛型右側的集合類型沒有任何影響? 以及為什么 Java 在沒有任何影響的情況下允許我們這樣做。我使用的是 Java 1.6。 請解釋。

如果您不在左側提供泛型類型參數,則List被聲明為原始類型。 這意味着編譯器不知道在該列表中存儲什么是合法的或不合法的,而是依賴程序員執行適當的instanceof檢查和強制轉換。

原始類型還具有消除它們出現的類中的所有泛型類型信息的效果。

JLS 提供了對原始類型的更詳細的了解。 您應該會在 IDE 或編譯器中看到有關分配給原始類型的警告:

為確保始終標記可能違反類型規則的行為,對原始類型成員的某些訪問將導致編譯時未經檢查的警告。 訪問原始類型的成員或構造函數時編譯時未檢查警告的規則如下:

在對字段賦值時:如果左側操作數的類型是原始類型,那么如果擦除更改了字段的類型,則會出現編譯時未檢查警告。

在調用方法或構造函數時:如果要搜索的類或接口的類型(第 15.12.1 節)是原始類型,則如果擦除更改了方法的任何形式參數類型,則會出現編譯時未經檢查的警告或構造函數。

當形式參數類型在擦除時未更改(即使結果類型和/或 throws 子句更改)、從字段讀取或創建原始類實例時,方法調用不會發生編譯時未經檢查的警告類型。

Tom G 的回答很好,詳細解釋了一些事情,但我覺得您至少已經知道其中的一些內容,因為您這樣說:

我希望我會得到一些編譯錯誤

所以,讓我准確地談談那部分。

您沒有收到任何編譯錯誤的原因是因為在 Java 中添加了泛型作為事后的想法,因此,許多與泛型相關的問題本應是錯誤,而是降級為警告,以免破壞現有代碼。

最有可能發生的是這些警告在您的開發環境中被關閉。

糾正問題的步驟:

  1. 轉到 IDE 的選項

  2. 找到“警告”部分。

  3. 啟用一切

  4. 在您看到收到的大量警告后,請從地板上撿起您的下巴。

  5. 禁用所有沒有任何意義的警告,例如“硬編碼字符串”或“成員訪問權限不符合this ”,保留其他所有內容。 確保說“參數化類的原始使用”之類的內容是您保留的內容之一。

乍一看好像myList只能存儲String

乍一看,也許。 但是意識到沒有“只能存儲字符串的列表”這樣的東西真的很重要,至少在標准 API 中是這樣。

只有List ,如果您嘗試向其中添加不是String的內容(即通過將其聲明為List<String> myList ,則必須向編譯器包含正確的指令以List<String> myList

如果您將其聲明為“plain old List ”,則編譯器沒有關於允許或禁止您放入其中的內容的說明,因此您可以在支持數組的類型范圍內存儲任何內容,即任何Object

您在賦值的 RHS 上說new ArrayList<String>()是無關緊要的:Java 不會嘗試跟蹤分配給變量的值。 變量的類型是您聲明的類型。

“...泛型右側的集合類型沒有任何影響”大部分是正確的。 當“var”關鍵字替換“List”時,右側泛型確實有效果。 下面的代碼創建了一個字符串的 ArrayList。

var myList = new ArrayList<String>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM