【问题标题】:Is it possible in Java to narrow down generic type in subclass of generic class?在 Java 中是否可以缩小泛型类的子类中的泛型类型?
【发布时间】:2021-08-06 17:52:47
【问题描述】:

在 Java 中是否可以缩小泛型类的子类中的泛型类型? 我的情况是这样的:

class C<T> {
  protected T foo() {...}
  protected void bar(Supplier<T> foobar) {...}
}

class A<T extends B> extends C<T> {
  public void someMethod(){
    B b = foo(); // Compiler does not complain
    bar(() -> createB()); // Compiler complains with "Type mismatch: cannot convert from B to T"
  }
}

也许我所做的完全是愚蠢的,但我不明白为什么编译器不抱怨 foo(),而是抱怨 bar()。

非常感谢任何有关如何执行此操作或为什么不执行此操作的建议 :)

亲切的问候, 托马斯

【问题讨论】:

  • createBB 在哪里?
  • TB,但 B 不一定是 Tclass D extends B {} 在第二种情况下中断,但显然您可以将 D 分配给 B
  • 天哪,你说的太对了。为了解决这个问题,“createB()”也必须是 T 类型的泛型!非常感谢!

标签: java generics types


【解决方案1】:

这是一个差异问题。您有 A&lt;T extends B&gt; 的子类型 C&lt;T&gt;。我们也有

class C<T> {
  protected T foo() {...}
  protected void bar(Supplier<T> foobar) {...}
}

现在,当你这样做时

B b = foo();

foo() 返回T。我们知道(从类声明中)T extends B 是真的。向上转换到超类型总是安全的,所以每个T 都是B。现在考虑

bar(() -> createB());

createB 我猜是一个返回B 的函数。 bar 期待 Supplier&lt;T&gt;。也就是说,bar 期待产生T 的东西。 createB 是否产生 T?好吧,它会产生一个B。我们可以将B 向上转换为T 吗?不,我们知道T extends B,但是要将B 向上转换为T,我们需要知道相反的情况:B extends T

bar 中的T 出现在参数位置(逆变),而foo 中的T 出现在返回位置(协变)。这解释了施法能力的差异。如果我们写了

class A<T super B> extends C<T> {
  ...
}

那么你可以做bar 的例子,但不能做foo 的例子,因为我们有相反的关系。

请参阅与此问题相关的What is PECS。更多的是关于调用站点的差异,但关于差异的讨论仍然是相关的。

【讨论】:

    【解决方案2】:

    根据@luk2302 的评论:createB 本身必须是通用的,以便您可以参数化 IT 以返回 T extends b

    【讨论】:

      猜你喜欢
      • 2013-05-02
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多