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 行未注释,则以下内容将无法编译:

compound.react(new Organic());

在第二个示例中,允许使用脂肪族及其超类型。那么为什么不允许使用脂肪族?

在第一个例子中,为什么new Organic不允许?

第一个编译器错误:

- 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)
4

4 回答 4

5

你的第一个声明

Organic<? extends Organic> compound

表示compound 可能是一个Organic<SomeSubtypeOfHexane>(因为Aliphaticextends OrganicHexaneextendsAliphaticSomeSubtypeOfHexaneextends Hexane)。

在这种情况下compound.react(new Organic())compound.react(new Aliphatic())compound.react(new Hexane())会导致类型错误,因为Eincompound必须是 a SomeSubtypeOfHexane(或其子类型)。


你的第二次声明

Organic<? super Aliphatic> compound

意味着这compount 可能是一个Organic<Aliphatic>.

在那种情况下compound.react(new Organic())会导致类型错误,因为E必须是一个Aliphatic(或其子类型)。


请记住,使用A<? extends B>or声明变量A<? super B>

  • 扩展了可以分配给它的对象的数量,因此,
  • 限制可以对变量执行的操作。

由于类的确切类型是未知的(只有一个约束是已知的),编译器必须在安全方面犯错,并且不允许某些非协变或逆变的操作。(如果你还不熟悉它,协变和逆变是这类泛型的科学背景。)

于 2012-10-30T06:49:23.823 回答
2

该主题问题也在其他几个地方进行了讨论,例如:

这实际上是Java证书准备书中的一个问题,来自上次测试(问题34)。准备书是根据课本

即使有了这里和其他链接下的解释以及书中的文字,我也不清楚解决方案,因为这些解释主要基于List 界面和阅读,我认为这是一些内部集合特定的解决方案。

但是,如果您在一侧看到List接口和add -method的定义,在另一侧看到带有react -method 的Organic类,您会注意到它们的定义方式相似。

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

看看这个的解释:

于 2016-04-17T18:42:34.277 回答
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

于 2012-10-30T06:42:04.207 回答
0

你做了一些混合。
Organic<E>的类型等于Organic
你不能执行
new Organic()); 你至少必须考虑执行
new Organic<Object>()); 这只是我能想到的一个编译错误
这当然对你的其他对象实例有效。

于 2012-10-30T06:38:02.627 回答