在尝试了解Java通用类型和通配符#34;?"的用法时,我尝试了以下内容:
List<?> li = new ArrayList<Integer>();
List<Integer> li2 = new ArrayList<Integer>();
li2.add(new Integer(6));
li = li2;
以上编译并运行正常。但如果我尝试:
li.add(new Integer(5));
我遇到编译错误(使用Oracle JDeveloper作为IDE):
Error(24,9): cannot find method add(java.lang.Integer)
为什么以上不编译但作业li=li2
没问题?另外,如果我想调用li.add(...)
什么是可接受的参数值?
答案 0 :(得分:3)
?
是一个通配符类型,包含所有引用类型。将分配给类型?
的值必须可分配给任何引用类型。 Integer
不能分配给所有引用类型(例如,String s = new Integer(1);
失败)。实际上,在Java中,可分配给所有引用类型的唯一值是null
,这是您可以添加到List<?>
的唯一值
其他有趣的组合:
? super Number
是包含Object
和Number
类型的范围。当你写这样一个值时,它必须是Object
和Number
,即。 Integer
会好的。阅读此类值时,它将为Object
或Number
(因此,Object
)。
? extends Number
是包含类型Number
及其所有子类型的范围。当你写这样一个值时,它必须是Number的所有子类型的类型,即。它必须是null
。读取这样的值时,它将是Number
。
答案 1 :(得分: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)
方法是不安全的,因为会允许您将String添加到整数列表,反之亦然(或任何其他东西)。