使用通配符泛型时无法识别基类

问题描述 投票:0回答:1

为什么以下不起作用?

A b1 = new B();

Function<? super B, ? extends A> function = x -> new B();

A apply = function.apply(b1);

它给出错误“需要类型捕获?超级 B,提供 A”

上面的片段B扩展了A,那么为什么会失败呢?错误发生在 .apply(b1) 处。

请帮助我理解这一点..

java generics inheritance compiler-errors functional-programming
1个回答
0
投票

通用通配符很难理解。它们允许您编写通用算法,但代价是您可以假设值/参数/返回类型。我发现有时尝试为通用通配符类型生成可能的合法分配的不同示例会有所帮助,并且他们尝试查看用法与合法分配冲突的地方。

根据您的示例:

import java.util.function.Function;

class A {
}

class B extends A {
}

public class Main {
  public static void main(String[] args) {
    A a = new B();
    B b = new B();

    // Declare a generic wildcard function var that can be
    // assigned any of a set of functions but we (and the
    // compiler don't know which function really.
    Function<? super B, ? extends A> function;

    // Show some functions that can legally be assigned
    switch((int) (Math.random() * 4)) {
      case 0:  function = (A x) -> new A(); break;
      case 1:  function = (A x) -> new B(); break;
      case 2:  function = (B x) -> new A(); break;
      case 3:  function = (B x) -> new B(); break;
      default: function = null; // not possible 
    }

    // Try to use the functions - note that we don't know what
    // actual function was assigned to the generic variable -
    // any attempts to use the function must be allowed by all
    // of the possible assignable functions above.

    A apply1 = function.apply(a);
    // error: incompatible types: A cannot be converted to CAP#1
    // Not allowed because cases 2 and 3 above require a 'B'
    // parameter so the generic wildcard function variable cannot
    // accept an 'A' argument. Doesn't matter if the 'A' arg is
    // actually pointing at a 'B' value or not - compiler must only
    // allow code that works for any assignable value for 'A a'.

    A apply2 = function.apply(b);
    // This is okay - all cases will accept a 'B' argument.
    // 'B' arg can be passed to method with an 'A' parameter.

    B apply3 = function.apply(b);
    // error: incompatible types: CAP#1 cannot be converted to B
    // Arg 'B' is ok, but cannot assign returned result to 'B' var.
    // Not allowed because cases 0 and 1 are functions that return
    // an 'A' return type which cannot be assigned to 'B' var.
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.