简体   繁体   English

将Java通用类型与通配符“?”一起使用

[英]Using java generic types with wild card “?”

While trying to understand java generic types and usage of wild card "?", I tried the following: 在尝试了解Java通用类型和通配符“?”的用法时,我尝试了以下操作:

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

The above compiles and runs fine. 上面的代码可以正常运行。 But if I try: 但是,如果我尝试:

li.add(new Integer(5));

I get following compilation error (using Oracle JDeveloper as IDE): 我收到以下编译错误(使用Oracle JDeveloper作为IDE):

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

Why does the above not compile but the assignment li=li2 is fine? 为什么上面的代码不能编译,但是赋值li=li2很好? Also if I want to call li.add(...) what is an acceptable parameter value? 另外,如果我想调用li.add(...)什么是可接受的参数值?

? is a wildcard type, encompassing all reference types. 是通配符类型,包含所有引用类型。 Values that are going to be assigned to the type ? 将要分配给类型的值? must be assignable to any reference type. 必须可分配给任何引用类型。 Integer is not assignable to all reference types (for example, String s = new Integer(1); fails). Integer不能分配给所有引用类型(例如, String s = new Integer(1);失败)。 In fact, in Java the only value assignable to all reference types is null , which is the only value you can add to List<?> 实际上,在Java中,可分配给所有引用类型的唯一值是null ,这是可以添加到List<?>的唯一值List<?>

Other fun combinations: 其他有趣的组合:

? super Number ? super Number is a range including types Object and Number . ? super Number是一个范围,包括ObjectNumber类型。 When you write such a value, it has to be both Object and Number , ie. 当您编写这样的值时,它必须同时是ObjectNumber Integer would be okay. Integer就可以了。 When reading such a value, it will be either Object or Number (so, Object ). 当读取这样的值时,它将是ObjectNumber (即Object )。

? extends Number ? extends Number is a range including types Number and all its subtypes. ? extends Number是一个范围,包括Number类型及其所有子类型。 When you write such a value, it has to be of a type of all subtypes of Number, ie. 当您编写这样的值时,它必须是Number的所有子类型的类型,即。 it has to be null . 它必须为null When reading such a value, it will be a Number . 当读取这样的值时,它将是一个Number

A call to "li" will not bother whether you assigned it an ArrayList<Integer> or a LikedList<String> , it will work only on the declared type, that is List<?> . 调用“ li”将不会影响您是否为其分配了ArrayList<Integer>LikedList<String> ,它仅适用于声明的类型,即List<?>

When you declare a generic parameter, it can be applied to return types and to method arguments. 声明通用参数时,可以将其应用于返回类型和方法参数。 For example, in a List<String> , you will have a String get(int i) and a void add(String) methods. 例如,在List<String> ,您将具有String get(int i)void add(String)方法。

Both are safe, cause with this methods you can only add (and retrieve) String's from the list. 两者都是安全的,因为使用此方法,您只能从列表中添加(和检索)字符串。

On a List<?> you will have a Object get(int i) method, because whatever is in the list it can safely be cast to Object, be it Integer or String. List<?>您将具有Object get(int i)方法,因为列表中的任何内容都可以安全地强制转换为Object,无论是Integer还是String。

However, offering a void add(Object) method, is unsafe, cause would permit you to add a String to an Integer list or vice versa (or any other thing). 但是,提供一个void add(Object)方法是不安全的,因为它将允许您将String添加到Integer列表中,反之亦然(或其他任何事情)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM