2012-10-30 135 views
4

就在我以爲我終於明白了泛型,我碰到下面的例子就是:泛型超與延伸

public class Organic<E> { 
      void react(E e) { } 
      static void main(String[] args) { 
      //1: Organic<? extends Organic> compound = new Aliphatic<Organic>(); 
      //2: Organic<? super Aliphatic> compound = new Aliphatic<Organic>(); 
      compound.react(new Organic()); 
      compound.react(new Aliphatic()); 
      compound.react(new Hexane()); 
} } 
class Aliphatic<F> extends Organic<F> { } 
class Hexane<G> extends Aliphatic<G> { } 

它說,如果第1行註釋掉,下面將無法編譯:

compound.react(new Organic()); 
    compound.react(new Aliphatic()); 
    compound.react(new Hexane()); 

而如果線2 ucommented,以下將不編譯:

compound.react(new Organic()); 

在第二考試PLE,脂肪族和它的超類型是允許的。那麼,爲什麼不允許脂肪含量?

在第一示例中,爲什麼不能new Organic允許?

1編譯器錯誤:

- The method react(capture#1-of ? extends Organic) in the type Organic<capture#1-of ? extends Organic> is not applicable for the arguments (Organic) 
- The method react(capture#2-of ? extends Organic) in the type Organic<capture#2-of ? extends Organic> is not applicable for the arguments (Aliphatic) 
- The method react(capture#3-of ? extends Organic) in the type Organic<capture#3-of ? extends Organic> is not applicable for the arguments (Hexane) 

第二編譯器錯誤:

- The method react(capture#1-of ? super Aliphatic) in the type Organic<capture#1-of ? super Aliphatic> is not applicable for the arguments (Organic) 
+0

您是否嘗試過這個自己,你得到了什麼編譯器錯誤? –

+1

我知道我得到了什麼,我不明白爲什麼。 – Maggie

+0

[Java中的之間的區別]的可能的重複](http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java) – dimo414

回答

5

你的第一個聲明

Organic<? extends Organic> compound 

意味着compound可能Organic<SomeSubtypeOfHexane>(因爲Aliphatic延伸OrganicHexane延伸AliphaticSomeSubtypeOfHexane延伸Hexane)。

在這種情況下,compound.react(new Organic())compound.react(new Aliphatic())compound.react(new Hexane())會導致一種類型的錯誤,因爲在Ecompound必須是SomeSubtypeOfHexane(或其子類型)。


你的第二個聲明

Organic<? super Aliphatic> compound 

意味着compount可能Organic<Aliphatic>

在這種情況下,compound.react(new Organic())將導致類型錯誤,因爲E必須是Aliphatic(或其子類型)。


記住聲明使用A<? extends B>A<? super B>

  • 延伸的可以分配給它的對象的量的變量,並且,在結果,
  • 限制什麼可以用變量完成。

由於類的確切類型是未知的(僅一個約束是已知的),編譯器必須寧可安全的側面和禁止,它們或者不CO-或逆變某些操作。 (如果你不熟悉它,Co- and contravariance是這些類型的泛型的科學背景。)

0

你做了一些組合。
Organic<E>確實在其類型Organic相等。
您不能執行
new Organic()); 您必須至少考慮執行
new Organic<Object>()); 而這僅僅是一個編譯錯誤,我能想到的
這當然是有效的其他對象實例。

1

我想你是誤會你在你的react()方法作爲參數設置

嘗試改變

void react(E e) { } 

void react(Organic<E> e) { } 

看出區別。您正在尋找對象:Organic<E>Aliphetic<E>Hexane<E>

Organic<E>E

也不Aliphetic<E>E

Hexane<E>E

2

主題問題在其他幾個地方,如還討論:

這實際上是從最後一次測試(問題34)開始的Java certificate preparation這本書的一個問題。本書的編寫基於lessons book

即使在這裏和其他鏈接和本書中的解釋下,解決方案對我來說也不是很清楚,因爲解釋主要基於列表界面和閱讀,我認爲它是一些內部集合特定soluton。

但如果你看到名單接口的定義和一側添加 - 方法和該有機類及其反應在另一邊 - 方法,你會發現,他們被定義以類似的方式。

public interface List<E> extends Collection<E> { 
    ... 
    boolean add(E e); 
    ... 
} 

public class Organic<E> { 
    ... 
    void react(E e) { } 
    ... 
}            

因此,所有基於List接口的解釋都可以在任何地方找到,這些問題也適用於這個問題。

List<? extends String> list1 = new ArrayList<String>(); 
List<? super String> list2 = new ArrayList<String>(); 
list1.add(new String()); //The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String) - // compile-time error 
list2.add(new Object()); //The method add(capture#2-of ? super String) in the type List<capture#2-of ? super String> is not applicable for the arguments (Object) - // compile-time error 

看看說明就這一個: