带有钻石操作符的通配符

Ank*_*mba 7 java generics wildcard diamond-operator

如果我想做这样的事情:

List<?> unknownList = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

那么代码编译并运行正常,但其类型ArrayList创造?

在这一行之后,如果我这样做了:

        unknownList.add("str"); //compilation error
Run Code Online (Sandbox Code Playgroud)

它给出了编译错误:

error: no suitable method found for add(String)
        unList.add("str");
              ^
method List.add(int,CAP#1) is not applicable
  (actual and formal argument lists differ in length)
method List.add(CAP#1) is not applicable
  (actual argument String cannot be converted to CAP#1 by method invocation conversion)
method Collection.add(CAP#1) is not applicable
  (actual argument String cannot be converted to CAP#1 by method invocation conversion)
where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?
Run Code Online (Sandbox Code Playgroud)

这个错误是什么,将钻石操作符与通配符一起使用是否合适?如果是,那么WHERE ???

Jof*_*rey 4

但是 ArrayList 创建的是哪种类型呢?

类型参数只是在编译时应用的约束,但类型擦除会通过擦除来替换所有出现的类型参数(在您的情况下为Object)。因此,如果您询问运行时类型,它将是一个普通类型ArrayList(您可以将其视为ArrayList<Object>)。

使用带有通配符的菱形运算符是否合适?如果是,那么在哪里???

不。当您使用菱形运算符创建泛型类的新对象时,这意味着您不希望类型参数上出现冗余。它不应与通配符声明的变量组合使用,因为通配符声明的变量没有具体的类型参数。

总而言之,你不应该写:

List<?> unknownList = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

<?>仅当类型确实不重要时才应使用通配符。特别是,如果您想将项目添加到列表中,请不要使用通配符,因为添加项目意味着您知道要添加什么类型

例如,当您不访问该值而只是传递列表时,或者您只是将列表项作为普通对象访问时,它可能会用作方法的参数。