2012-10-30 60 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 

看看说明就这一个: