为什么泛型超类型的Java类型推断在此中断?
给出以下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
、list2
和list3
的表达式工作正常。但是,在Eclipse中初始化list4
的表达式因以下错误而中断:
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
。那么,当类型推断适用于list1
到list3
时,为什么类型推断会中断list4
(就这一点而言,也适用于optionalEntry
的赋值)
特别是,我不明白为什么对list1
的赋值有效,而对list4
的赋值无效
# 1 楼答案
因此,让我们显式地编写我们期望推断的类型。此外,我们将把声明放在用法附近
SimpleEntry<xyz>
是一个Entry<xyz>
,所以这很好Optional<xyz>
是一个微不足道的Optional<xyz>
Optional<xyz>
又是一个微不足道的Optional<xyz>
啊
Optional<SimpleEntry<xyz>>
不是一个Optional<Entry<xyz>>
您可以使用
Optional<? extends Entry<xyz>>
# 2 楼答案
我假设您理解为什么不能将
Optional<SimpleEntry<Integer,String>>
分配给类型为List<Optional<Entry<Integer, String>>>
的变量。如果没有,请阅读问题和建议;A Is List a subclass of List? Why are Java generics not implicitly polymorphic?但是,您的问题是为什么
list1
声明有效,而list4
声明无效list1
和list4
声明之间存在差异。对于list1
,表格为:在这种情况下,
Arrays.asList
方法的类型变量T
尚未固定为特定类型。它的上限为SimpleEntry<Integer, String>
(类型为simpleEntry
)根据Java Language Specification, section 18.5.2, "Invocation Type Inference",编译器将通过将
asList
(List<T>
)的返回类型约束为调用上下文目标类型(List<Entry<Integer, String>>
),进一步约束类型T
这是可能的;当编译器选择T为
Entry<Integer, String>
时,整个表达式都适合,因为SimpleEntry<Integer, String>
类型的值可以分配给Entry<Integer, String>
类型的变量对于
list4
,表格为:这里,
T
最初被限制为Optional<SimpleEntry<Integer, String>>
的上限。表达式上下文的目标类型是List<Optional<Entry<Integer, String>>>
。编译器不可能找到一个既适合两者的T
无法将类型为
Optional<SimpleEntry<Integer, String>>
的值分配给类型为Optional<Entry<Integer, String>>>
的变量这就是编译器抱怨的原因
简单地说
更简单地说,对于泛型类型不受约束且存在约束泛型类型的表达式上下文的方法,它适用于一个层次的参数化
你可以说
但在更深层次的参数化中,它不起作用