簡體   English   中英

Java泛型和instanceof關鍵字

[英]Java generics and the instanceof keyword

所以,我正在查看Oracle Java教程,特別是這段代碼;

List<EvenNumber> le = new ArrayList<>();
List<? extends NaturalNumber> ln = le;
ln.add(new NaturalNumber(35));  // compile-time error

可以在這里找到。 這是我的理解(並且請糾正我,如果我錯了)上面的代碼將無法工作,因為編譯器不知道ln引用了EvenNumbers列表,因此這可以防止您意外添加任何可能是列表的元素的超類型。 如果是這種情況,那么為什么如果你有一個像Number num = new Integer(6);這樣的語句呢Number num = new Integer(6); 如果編寫if語句,編譯器能夠正確地確定num是一個Integer對象; if (num instanceof Integer) {...}

我想我的問題是,編譯器如何能夠確定num在第二個示例中引用了Integer對象,但是在第一個示例中無法確定ln是否引用了List<EvenNumber>對象?

你的兩個例子是彼此相反的。

Integer 一個Number ,所以

List<Number> list;
list.add(new Integer(1)); // compiles

EvenNumber 一個NaturalNumber而不是相反 ,所以

List<EvenNumber> list;
list.add(new NaturalNumber(1)); // compile error

因為當EvenNumber是一個NaturalNumberNaturalNumber 不是 (一定)的EvenNumber

如果在參考案例中交換IntegerNumber然后重做它,它應該是有意義的,即這將編譯:

List<NaturalNumber> list;
list.add(new EvenNumber(2)); // compiles OK

通常,編譯器能夠確定很多東西,並在優化代碼時使用其觀察結果。

但是,Java是靜態和強類型的語言,編譯器在類型安全方面沒有自由。

1)禁止添加到ln列表,因為人們不確切地知道它應該包含哪種類型的元素。 在您的示例中,此規則阻止將列表置於無效狀態。

2) “......編譯器能夠正確地確定num是一個整數......”

不是這樣,編譯器不能確定它(盡管如果Java是弱類型語言的話)。

3) num instanceof Integer

這是在運行時評估的,而不是在編譯時評估的。 但是,以下將產生編譯時錯誤:

num instanceof String

因為Number永遠不能是String

這是無法編譯的主要原因是由於這種方式? extends T ? extends T表現。 一般來說,人們應該熟悉Producer Extends,Consumer Super或PECS。

現在,我還沒有看過這個特殊的代碼示例,但我認為EvenNumber的層次結構擴展了NaturalNumber 這使得賦值語句有效,因為EvenNumber是一個NaturalNumber (盡管我打賭數學家們正在NaturalNumber這個)。

在上面突出顯示的場景中,您無法向集合中添加任何內容的原因是它主要用於讀取。 也就是說,列表是生產者 ,因此它與extends綁定。

如果您想要讀取寫入集合,您只需要保留通配符。

你的第二個例子與泛型完全無關 ,而是簡單的繼承。 由於Integer繼承自Number ,我們可以說Integer是一個Number ,因此可以被視為一個數字。 任何繼承的類都具有此功能。 檢查Liskov替代原則以獲取更多信息。

暫無
暫無

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

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