【问题标题】:Generics super vs. extends泛型超级与扩展
【发布时间】:2012-10-19 11:32:29
【问题描述】:

就在我以为我终于理解了泛型的时候,我偶然发现了下面这个例子:

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)

【问题讨论】:

标签: java generics scjp generic-type-argument


【解决方案1】:

你的第一个声明

Organic<? extends Organic> compound

意味着compound 可以是Organic&lt;SomeSubtypeOfHexane&gt;(因为Aliphatic 扩展Organic、Hexane 扩展Aliphatic 和SomeSubtypeOfHexane 扩展Hexane)。

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


你的第二个声明

Organic<? super Aliphatic> compound

表示compount 可能是Organic&lt;Aliphatic&gt;。

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


请记住使用A&lt;? extends B&gt; 或A&lt;? super B&gt; 声明变量

  • 扩展可以分配给它的对象数量,因此,
  • 限制变量可以做什么。

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

【讨论】:

    【解决方案2】:

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

    这实际上是来自Java certificate preparation 的书中的一个问题,来自上次测试(问题34)。准备书基于lessons book。

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

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

    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
    

    看看这个的解释:

    【讨论】:

      【解决方案3】:

      我认为您误解了您在 react() 方法中设置的参数

      尝试改变

      void react(E e) { }
      

      到

      void react(Organic<E> e) { }
      

      看看有什么不同。你在找对象:Organic&lt;E&gt;Aliphetic&lt;E&gt;Hexane&lt;E&gt;

      不是Organic&lt;E&gt; 是E

      Aliphetic&lt;E&gt; 也不是 E

      Hexane&lt;E&gt; 也不是 E

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-09-18
          • 1970-01-01
          • 2012-08-30
          • 2018-11-20
          • 2015-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多