让我们研究一些使用通配符的通用实例情况:
1
这段代码
List<?> list = new ArrayList<?>();
生成以下错误:
required: class or interface without bounds
found: ?
2
但是这个
List<?> list = new ArrayList< Set<?> >();
编译成功
3
还有这个:
List<Set<?>> list = new ArrayList< Set<?> >();
编译也成功
4
但是这个:
List<Set<Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
产生
required: List<Set<Map<?,?>>>
found: ArrayList<Set<Map<String,String>>>
5
List<Set<?>> list = new ArrayList< HashSet<?> >();
生成
required: List<Set<?>>
found: ArrayList<HashSet<?>>
我对这些输出感到很困惑。
我看到以下规律:
我只能在第一级将 ?
从左侧部分替换为右侧部分,<> 中的类型应该相同,只是 ?和 ?是禁止的。
但我不明白为什么?
您能否提供如何使用通配符实例化泛型的通用规则?
最佳答案
- 您不能使用通配符直接实例化类型。类型参数在实例化时需要是实际类型,因此会产生编译器错误。
代码:
List<?> list = new ArrayList<?>();
- 以下编译成功。
代码:
List<?> list = new ArrayList< Set<?> >();
您可以使用通配符作为类型参数的泛型类型参数,例如 Set<?>
,一套任何东西。此外,任何类型参数都将匹配通配符 ?
在左边。
- 这也编译成功:
代码:
List<Set<?>> list = new ArrayList< Set<?> >();
类型参数匹配,?
没有像上面 (1) 中那样直接使用。
- 以下不编译:
代码:
List<Set<Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
这是因为即使 Map<String, String>
是 Map<?, ?>
, 一个 List<Set<Map<String, String>>>
不是 List<Set<Map<?, ?>>>
. Java 泛型是不变的,这意味着类型参数必须匹配; “is-a”关系必须在上限中使用通配符明确指定。例如。此更改通过在左侧引入上界通配符来编译。
List<? extends Set<? extends Map<?,?>>> list = new ArrayList< Set<Map<String,String>> >();
- 由于与上述 (4) 相同的原因,以下内容无法编译:
代码:
List<Set<?>> list = new ArrayList< HashSet<?> >();
即使 HashSet<?>
是 Set<?>
,由于 Java 的不变泛型,一个 ArrayList<HashSet<?>>
不是 List<Set<?>>
.在左侧引入通配符作为上限也适用于此:
List<? extends Set<?>> list = new ArrayList< HashSet<?> >();
关于java - 如何使用通配符实例化泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26146371/