簡體   English   中英

泛型和原始類型

[英]Generics and raw types

我使用泛型編寫了一些代碼,但遇到了以下我無法理解的情況:

我有接口 IpRange 和以下類:

public class Scope<IpRange<T extends IP>> {
     List<IpRange<T>> rangesList;
     public List<IpRange<T>> getRangesList() {return rangesList;}
}

現在從一些測試類,如果我寫以下內容:

Scope<Ipv4> myScope = new Scope<Ipv4>(); 
scope.getRangesList().get(0)

我正在獲取 IpRange 類型的對象,但如果我使用原始類型並執行以下操作:

Scope myScope = new Scope();
scope.getRangesList().get(0)

我正在獲取 Object,除非我明確將其強制轉換為 Range,否則我無法使用 ipRange 方法。

如果它本來是List<T>我明白了,因為我使用原始類型編譯器無法知道列表項的實際類型是什么,但在這種情況下它將始終是 IpRange 類型,所以為什么我我沒有得到對象?

問題是,當我創建范圍時,我不一定知道實際的范圍類型。 考慮這個構造函數: public Sc​​ope(String rangeStringList); 據我所知,字符串可能是“16.59.60.80”或“fe80::10d9:159:f:fffa%”。 但我所知道的是,我將一些 IpRange 對象傳遞給了編譯器,並且無論是 ipv4 還是 ipv6,我都希望能夠使用這個接口。 而且由於即使我使用行類型,編譯器也可以確定這是 ipRange,我想知道為什么 java 選擇這樣做

人們指出在使用原始類型時所有泛型類型信息都被剝離了,並暗示這是為了向后兼容。 我想如果沒有解釋,這可能不會令人滿意,所以我將嘗試解釋如何使用像您這樣的代碼遇到這樣的問題。

首先,假設您在那里編寫的代碼是舊庫的一部分,並且您正在通過添加泛型來升級庫。 也許它是一個流行的庫,很多人都使用過舊代碼。

有人可能已經使用您庫中的類做了這樣的事情:

private void someMethod(Scope scope, Object object) {
  scope.getRangesList().add(object);
}

現在,看看這個,我們知道 Object 可能不是 IpRange 類型,但這是一個私有方法,所以讓我們假設類型檢查是由調用 someMethod 的任何方法有效執行的。 這可能不是好的代碼,但如果沒有泛型,它確實可以編譯並且可以正常工作。

想象一下,寫這個的人升級到你的庫的新版本以獲得一些新功能或未實現的錯誤修復,與此同時,他們現在可以使用你的泛型類獲得更多的類型安全性。 但是,他們可能不想使用它,像上面使用原始類型的代碼提取物一樣。

您實際上建議的是,即使 'scope' 是原始類型,從 getRangesList() 返回的 List 必須始終為 List<IpRange<? 擴展 IP>>,所以編譯器應該注意到這一點。

如果是這種情況,上面將對象添加到列表的遺留代碼將不再編譯而不被編輯。 這是在不忽略原始類型的所有可用泛型類型信息的情況下破壞向后兼容性的一種方式。

是的,如果您使用原始類型,則該方法的其余部分中的所有泛型都將“關閉”,並且所有泛型類型都變為原始類型,即使它們不會受到原始類型缺少的泛型參數的影響。

如果您使用原始類型,則所有泛型類型信息都會從類中剝離,包括在實例上調用的靜態方法。

這樣做的原因是為了與 java 1.4 向后兼容。

暫無
暫無

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

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