我知道这可能与泛型和协变返回类型有关。但我撑不过去了。
给定Apple扩展Fruit的两个类。
public class TestReturnValue {
public static Supplier<? extends Fruit> conFruitExt = Apple::new;
public static Supplier<Fruit> conFruit = Apple::new; // Compiles
public static final Supplier<Fruit> supApple = supplyApple(); // Compile ERROR
private static Supplier<Apple> supplyApple() {
return Apple::new;
}
public static void main(String[] args) {
Fruit fruitExt = conFruitExt.get();
Fruit fruit = conFruit.get();
System.out.println(fruitExt);
System.out.println(fruit);
}
}
conFruitExt和conFruit之间有什么不同?它们都是Apple的构造函数,调用get()
可以创建苹果实例。
conFruitExt类型的额外? extends
部分有什么不同吗?
更新1 2020/11/19
正如建议的答案所说,jonrsharpe在泛型中的问号,Supplier<Fruit>
不编译为Suppier<Apple>
,所以public static final Supplier<Fruit> supApple = TestReturnValue::supplyApple;
不编译。
但由于方法supplyApple()
的返回值表明Apple::new
是Supplier<Apple>
的类型,public static Supplier<Fruit> conFruit = Apple::new
为什么编译。它不是给Supplier<Fruit>
分配了一个Supplier<Apple>
实例吗?
这样做:
public static Supplier<Fruit> conFruit = Apple::new;
您正在Apple::new
中创建poly表达式。这些是编译器在使用上下文中推断出来的。想想看:如果我只给你Apple::new
,你能告诉我那是什么吗?Supplier
?或者Provider
(可能存在这样的功能接口(等等?因此,这些类型是从使用的周围环境中得出的。就像编译器做的那样:
public static Supplier<Fruit> conFruit = (Supplier<Fruit>) () -> new Apple();
这是完全合法的(这不是发生的事情,而是为了让你更容易理解(。
在另一种方法中,您已经明确地告诉了返回类型是什么:
private static Supplier<Apple> supplyApple() {...}
它是CCD_ 16。由于泛型是不变量,所以第二次赋值失败。