2014-09-25 71 views
2

在试图了解java泛型类型和外卡的使用,我试过如下:使用带有通配符的java泛型“?” “?”

  1. List<?> li = new ArrayList<Integer>();
  2. List<Integer> li2 = new ArrayList<Integer>();
  3. li2.add(new Integer(6));
  4. li = li2;

以上编译并运行良好。但是,如果我尝试:

li.add(new Integer(5)); 

我获得以下编译错误(使用Oracle JDeveloper作为IDE):

Error(24,9): cannot find method add(java.lang.Integer) 

为什么上面没有编译,但分配li=li2是好的?另外如果我想打电话给li.add(...)什么是可接受的参数值?

回答

3

?是通配符类型,包含所有参考类型。将要分配给类型?的值必须可分配给任何参考类型。 Integer不可分配给所有参考类型(例如,String s = new Integer(1);失败)。事实上,在Java中分配给所有引用类型的唯一值是null,这是您可以添加到List<?>

其他有趣的组合,唯一的价值:

? super Number是包括类型ObjectNumber一个范围。当你写这样一个值时,它必须是ObjectNumber,即。 Integer会没事的。当读取这样的值时,它将是ObjectNumber(so,Object)。

? extends Number是一个范围,包括Number及其所有子类型。当你写这样一个值时,它必须是所有Number的子类型,即。它必须是null。当读取这样的值时,它将是一个Number

2

对“li”的呼叫不会打扰您是否将其分配给ArrayList<Integer>LikedList<String>,它只对声明的类型起作用,即List<?>

当你声明一个泛型参数时,它可以应用于返回类型和方法参数。例如,在List<String>中,您将有一个String get(int i)和一个void add(String)方法。

两者都是安全的,因此使用此方法只能从列表中添加(并检索)String。

List<?>上,您将有一个Object get(int i)方法,因为列表中的任何内容都可以安全地转换为Object,可以是Integer或String。

但是,提供方法void add(Object)是不安全的,原因会允许您将字符串添加到整数列表,反之亦然(或任何其他事物)。