有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在Java中是否有可能缩小泛型类子类中的泛型类型?

在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()

任何关于如何做或为什么不做这件事的建议,我们都将不胜感激:)

亲切问候,, 托马斯


共 (2) 个答案

  1. # 1 楼答案

    这是一个差异问题。你有A<T extends B>一个C<T>的子类型。我们也有

    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<T>。也就是说,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. # 2 楼答案

    根据@luk2302 comment:createB本身必须是泛型的,这样就可以参数化它以返回T extends b