java - 为什么泛型父类(super class)型的 Java 类型推断会在这里中断?

标签 java generics type-inference

鉴于此 Java 代码:

import java.util.AbstractMap.SimpleEntry;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.Optional;

public class Test {
    public static void main(String[] args) {
        SimpleEntry<Integer, String> simpleEntry = new SimpleEntry<>(1, "1");
        Optional<Entry<Integer, String>> optionalEntry = Optional.of(simpleEntry);
        Optional<SimpleEntry<Integer, String>> optionalSimpleEntry = Optional.of(simpleEntry);

        List<Entry<Integer, String>> list1 = Arrays.asList(simpleEntry);
        List<Optional<Entry<Integer, String>>> list2 = Arrays.asList(optionalEntry);
        List<Optional<SimpleEntry<Integer, String>>> list3 = Arrays.asList(optionalSimpleEntry);
        List<Optional<Entry<Integer, String>>> list4 = Arrays.asList(optionalSimpleEntry);
    }
}

表达式初始化 list , list2list3工作正常。但是,表达式初始化 list4在 Eclipse 中出现此错误:
Type mismatch: cannot convert from List<Optional<AbstractMap.SimpleEntry<Integer,String>>>
to List<Optional<Map.Entry<Integer,String>>>

和这个错误 javac :
Test.java:16: error: incompatible types: inference variable T has incompatible bounds
        List<Optional<Entry<Integer, String>>> list4 = Arrays.asList(optionalSimpleEntry);
                                                                    ^
    equality constraints: Optional<Entry<Integer,String>>
    lower bounds: Optional<SimpleEntry<Integer,String>>
  where T is a type-variable:
    T extends Object declared in method <T>asList(T...)

但是AbstractMap.SimpleEntry直接实现Map.Entry .那么为什么类型推断会中断 list4当它适用于 list1list3 (以及分配给 optionalEntry ,就此而言)?

特别是我不明白为什么分配给 list1当分配给 list4 时有效才不是。

最佳答案

我想你明白为什么 Optional<SimpleEntry<Integer,String>>不能分配给 List<Optional<Entry<Integer, String>>> 类型的变量.如果没有,请阅读问答Is List a subclass of List? Why are Java generics not implicitly polymorphic?

但是,您的问题为什么list1声明有效,但 list4宣言。
list1之间有区别和 list4声明。对于 list1 ,形式为:

SimpleEntry<Integer, String> simpleEntry = ...;
List<Entry<Integer, String>> list = Arrays.asList<T>(simpleEntry);

在这种情况下,类型变量 TArrays.asList方法尚未固定到特定类型。它的上限为 SimpleEntry<Integer, String> ( simpleEntry 的类型)。

根据Java Language Specification, section 18.5.2, "Invocation Type Inference" ,编译器会进一步约束类型 T通过约束 asList 的返回类型( List<T> ) 到调用上下文目标类型 ( List<Entry<Integer, String>> )。

这个有可能;当编译器选择 T 为 Entry<Integer, String> ,整个表达式都适合,因为类型为 SimpleEntry<Integer, String> 的值可以分配给 Entry<Integer, String> 类型的变量.

对于 list4 ,形式为:
SimpleEntry<Integer, String> simpleEntry = new SimpleEntry<>(1, "1");
Optional<SimpleEntry<Integer, String>> optionalSimpleEntry = Optional.of(simpleEntry);
List<Optional<Entry<Integer, String>>> list4 = Arrays.asList<T>(optionalSimpleEntry);

在这里,T最初被限制为 Optional<SimpleEntry<Integer, String>> 的上限.表达式上下文的目标类型是 List<Optional<Entry<Integer, String>>> .编译器不可能想出 T两者都适合。

类型为 Optional<SimpleEntry<Integer, String>> 的值不能分配给 Optional<Entry<Integer, String>>> 类型的变量.

这就是编译器提示的原因。

简单来说

简单来说,对于泛型类型不受约束且存在约束泛型类型的表达式上下文的方法,它适用于一层深度的参数化。

你可以说
Dog dog = ...;
List<Animal> animals = Arrays.asList(dog);

但它不适用于更深层次的参数化。
Optional<Dog> optionalDog = ...;
List<Optional<Animal>> optionalAnimals = Arrays.asList(optionalDog);

关于java - 为什么泛型父类(super class)型的 Java 类型推断会在这里中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58945417/

相关文章:

java - 如何使用谷歌云数据存储模拟器和java实现docker镜像

c++ - 在这种情况下如何使模板类型推断起作用?

java - Java 规范中的方法类型推断

Java 多 -"where"关键字?

c# - 从方法返回通用任务时发生转换错误

f# - 不清楚的函数返回类型问题

JavascriptencodeURIComponent和Java解码问题

java - 交换按钮在android中的位置

Java:编辑并重新编译.jar?

具有泛型参数的 Swift 3 泛型扩展约束