为什么编译器会对List <! - ? - >和List <! - 进行处理?扩展对象 - >不同?

时间:2015-11-18 22:00:29

标签: java generics

请考虑以下代码:

import java.util.ArrayList;
import java.util.List;

public class UnboundedWildcardProblem {

    public static void main(String[] args) {
        List<?> a = new ArrayList();
        List<? extends Object> b = new ArrayList();
    }
}

List<?>的创建不会产生任何警告,但List<? extends Object>的创建会产生未经检查的警告:

Warning: java: unchecked conversion
  required: java.util.List<? extends java.lang.Object>
  found:    java.util.ArrayList

我搜索了可能的原因并找到了一些讨论:

List<?> vs List<? extends Object>

What's the difference between <?> and <? extends Object> in Java Generics?

但在阅读这些讨论之后,我认为List<?>List<? extends Object>是相同的。

那么,这种编译器行为的原因是什么?

修改

用于编译的单个标志是Xlint:unchecked标志。

1 个答案:

答案 0 :(得分:7)

  

List<?>的创建不会产生任何警告,但List<? extends Object>的创建会产生未经检查的警告

事实上,如果使用-Xlint:allXlint选项编译代码,则会收到List<?> a = new ArrayList();语句的警告,例如:

   warning: [rawtypes] found raw type: ArrayList
            List<?> a = new ArrayList();
                            ^
missing type arguments for generic class ArrayList<E>
where E is a type-variable:
  E extends Object declared in class ArrayList

但是,您没有获得未经检查的警告本身的原因是因为类型List<?>仅包含Java语言this section中提到的无界通配符规格:

  

从原始类或接口类型(§4.8)G到G<T1,...,Tn>形式的任何参数化类型都有未经检查的转换。

     

...

     

使用未经检查的转换会导致编译时未经检查的警告,除非所有类型参数Ti(1≤i≤n)都是无界通配符(§4.5.1),或者未经检查的警告被抑制通过SuppressWarnings注释(第9.6.4.5节)。

然而,在this section中,提到了:

  

通配符? extends Object等同于无界通配符?

显示编译器中的细微不一致。