调用带有List<String>
作为参数就像调用下面的方法,你的方法:
public static List<? super String> m(List<String> list) { ... }
考虑以下起始代码:
List<String> list = new ArrayList<>();
List<? super String> result = m(list);
这需要上面提到的方法和存储返回值转换为变量result
- 与方法的返回类型完全一致。
现在的问题是:什么变量 - 或更好的什么类型 - 你可以分配这个变量?所以我们谈论的是分配兼容性。
考虑这些任务:
List<String> result1 = result; // compiler error: type mismatch (not assignable)
List<Object> result2 = result; // compiler error: type mismatch (not assignable)
List result3 = result; // ok
List<?> result4 = result; // ok
List<? super String> result5 = result; // ok
List<? extends Object> result6 = result; // ok
要理解这个错误的性质,你必须知道,泛型是不变。这意味着,类型List<String>
不是List<Object>
的子类型 - 尽管类型String
和Object
具有这样的子类型层次结构。
所以,我们试图在这里的是:
- 分配
List<? super String>
到List<String>
=>失败,无分型
- 分配
List<? super String>
到List<Object>
=>失败,无分型
- 分配一个
List<? super String>
到List
=>成功,因为使用原始类型通常从类型检查中选择出来
- 将
List<? super String>
指定为List<?>
=>成功,因为List<?>
是所有List<...>
- 的超分配
List<? super String>
到List<? super String>
=>成功,因为...好...
- 分配
List<? super String>
到List<? ectends Object>
=>成功,因为List<? ectends Object>
是基本上与List<?>
相同。
注意,即试图分配List<? super String>
到List<? super CharSequence>
或List<? extends CharSequence>
也将失败。它们不在子类型层次结构中。
这是为什么?编译器不能保证实际列表实例化的类型与约束条件? super/extends CharSequence
相匹配。
例如,我问为什么我的'结果'不能成为'List
为什么你使用通配符作为返回类型?这是一个相当奇怪的事情... – fge
@fge那是库方法,不是我的。 – bladekp