如何使用通配符实例化generics?

让我们使用外卡研究一些通用的情况:

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> >(); 

生成

 required: List<Set<Map>> found: ArrayList<Set<Map>> 

 List<Set> list = new ArrayList< HashSet >(); 

生成

 required: List<Set> found: ArrayList<HashSet> 

我对这些输出很困惑。

我看到以下规律性:

我可以替换? 从右侧部分的左侧部分仅在第一级,并且类型应该在内并且只是? 和? 是禁止的。

但我不明白为什么?

你能提供如何使用通配符实例化generics的通用规则吗?

  1. 您不能使用通配符直​​接实例化类型。 实例化时,type参数必须是实际类型,因此会生成编译器错误。

码:

 List list = new ArrayList(); 
  1. 以下编译成功。

码:

 List list = new ArrayList< Set >(); 

您可以使用通配符作为类型参数的generics类型参数,例如Set ,一组任何东西。 此外,任何类型参数都将匹配通配符? 在左边。

  1. 这也成功编译:

码:

 List> list = new ArrayList< Set >(); 

类型参数匹配,和? 不直接用于上述(1)中。

  1. 以下内容无法编译:

码:

 List>> list = new ArrayList< Set> >(); 

这是因为即使MapMapList>>也不是List>> 。 Javagenerics是不变的,这意味着类型参数必须匹配; 必须使用上限中的通配符明确指定“is-a”关系。 例如,通过在左侧引入上限通配符来编译此更改。

 List>> list = new ArrayList< Set> >(); 
  1. 以下内容的编译原因与上述(4)相同:

码:

 List> list = new ArrayList< HashSet >(); 

即使HashSetSet ,由于Java的不变generics, ArrayList>不是List> 。 在左边引入通配符作为上限也适用于此:

 List> list = new ArrayList< HashSet >(); 
  1. 您无法使用通配符进行实例化。 您必须指定类型。 “?” 不是一种类型。
  2. 这没关系,因为你给List一个类型,即SetSet是一种类型。
  3. 正确。 ArrayListList的子类型。
  4. 这是事情变得丑陋的地方。 右手不是左手的子类型,因为Java处理类型参数的方式很复杂。 类型参数必须完全匹配,或者您必须使用协方差/逆变( stuff)。 List不是List的子类型。 它 List的子类型List List或只List
  5. 与上面相同。 如果您已将其声明为List> List>它会工作。