Luk*_*son 6 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);
}
}
Run Code Online (Sandbox Code Playgroud)
表达式可以初始化list,list2并且list3可以正常工作。但是,表达式初始化list4在Eclipse中因以下错误而中断:
Type mismatch: cannot convert from List<Optional<AbstractMap.SimpleEntry<Integer,String>>>
to List<Optional<Map.Entry<Integer,String>>>
Run Code Online (Sandbox Code Playgroud)
和此错误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...)
Run Code Online (Sandbox Code Playgroud)
可AbstractMap.SimpleEntry直接实施Map.Entry。那么,为什么类型推断歇list4时,它适合list1于list3(也为分配optionalEntry,对于这个问题)?
特别是我不明白为什么对分配不起作用list1时为什么对分配起作用list4。
我假设您明白为什么Optional<SimpleEntry<Integer,String>>不能分配给类型的变量List<Optional<Entry<Integer, String>>>。如果不是,请阅读 Q&A List是 List 的子类吗?为什么 Java 泛型不是隐式多态的?
但是,您的问题是为什么list1声明有效,但list4声明有效。
list1和声明之间存在差异list4。对于list1,其形式为:
SimpleEntry<Integer, String> simpleEntry = ...;
List<Entry<Integer, String>> list = Arrays.asList<T>(simpleEntry);
Run Code Online (Sandbox Code Playgroud)
T在这种情况下,方法的类型变量Arrays.asList尚未固定为特定类型。它的上限为SimpleEntry<Integer, String>( 的类型simpleEntry)。
根据Java 语言规范第 18.5.2 节“调用类型推断”,编译器将通过将( )T的返回类型约束为调用上下文目标类型 ( ) 来进一步约束类型。asListList<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);
Run Code Online (Sandbox Code Playgroud)
这里,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);
Run Code Online (Sandbox Code Playgroud)
但它不适用于更深层次的参数化。
Optional<Dog> optionalDog = ...;
List<Optional<Animal>> optionalAnimals = Arrays.asList(optionalDog);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
58 次 |
| 最近记录: |