当前位置: 首页 > 面试题库 >

泛型超级与扩展

诸葛文博
2023-03-14
问题内容

当我以为自己终于了解了泛型时,我遇到了以下示例:

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)

问题答案:

您的第一个声明

Organic<? extends Organic> compound

表示compound 可能 是一个Organic<SomeSubtypeOfHexane>(因为Aliphaticextends
OrganicHexaneextends AliphaticSomeSubtypeOfHexaneextended 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>

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

由于类的确切类型是未知的(只有 约束
是已知的),因此编译器不得不出于安全考虑而犯错,并禁止某些不是协变的或互变的操作。(如果您还不熟悉它,协方差和逆方差是此类泛型的科学背景。)



 类似资料:
  • 问题内容: 但是,我似乎仍然对super关键字感到迷茫: 当我们声明这样的集合时: 不应该相反吗?我们有一个列表,其中包含一些对象(类型未知),它们是的父对象Number。因此Object应该适合(因为它是的父项),而不应该。由于某种原因,情况恰恰相反。 只要我们有以下代码 编译上面的代码是不可能的(我的理智建议这是正确的行为),但是基本逻辑可以证明是相反的: 我知道这很疯狂,但这不是他们不允许使

  • 问题内容: 我正在尝试重构M类型确实扩展了任何内容的类和子类集,即使我们知道它必须是某种类型的子类也是如此。该类型已参数化,我希望其参数化类型可用于已经具有M值的子类。 有什么方法可以定义此类,而不必在参数列表中包括冗余的K和V泛型类型。我希望能够使编译器从子类映射到的M中推断出它们。 换句话说,我希望类声明看起来像这样: 从M的定义可以推断出K和V的类型。 问题答案: 问题在于,它们并没有真正地

  • 问题内容: 您如何进行这项工作: 不做 编辑 为什么这不起作用? 我正在将编译器消息标记为错误。 问题答案: Reimeus已经指出,您在编辑中要求的内容是不可能的。我只想扩展一下原因。 人们会认为您可以使用以下内容: 实际上,这就是我第一次看到这篇文章时想到的。但这实际上会导致编译器错误: 类型变量不能跟其他界限 为了帮助我解释原因,我想引用Victor Rudometov在OracleBlog

  • 问题内容: 我知道有关此主题的问题很多,但是很遗憾,这些问题无法帮助我消除歧义。首先,请看下面的例子。我不明白,为什么以下“添加”方法不起作用并因以下异常而中止: 线程“主”中的异常java.lang.Error:未解决的编译问题:类型为Cage的方法add(capture#2-of?extended Animal)不适用于参数(Rat) 这是不是一个相同的原因吗?如果是,则在此示例中我不理解它,

  • 我尝试通过以下方式为我的PageFactory创建存储: 因此,从代码部分您可以理解编译错误在哪里,尽管两者都是和从基本页扩展的T: 我必须从

  • 问题内容: 我不明白为什么要编译。我以为它检查了但没有检查? 问题答案: 泛型中的关键字在语义上与常规关键字略有不同。 当使用在泛型的上下文中,例如,这意味着,应该是一个类型的 任一 实现的接口(在情况下,当是接口), 或者 是子类(如果是一个类)。 可能的原因是,如果Generics中支持该关键字,则会使类型参数声明过于冗长。 例如,您将拥有: 相反,此方法的有效语法为: 实际上,您不需要关键字