Java 带菱形运算符的通配符

Java 带菱形运算符的通配符,java,generics,wildcard,diamond-operator,Java,Generics,Wildcard,Diamond Operator,如果我想做这样的事情: List<?> unknownList = new ArrayList<>(); unknownList.add("str"); //compilation error 它给出了编译错误: error: no suitable method found for add(String) unList.add("str"); ^ method List.add(int,CAP#1) is

如果我想做这样的事情:

List<?> unknownList = new ArrayList<>();
        unknownList.add("str"); //compilation error
它给出了编译错误:

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 ?
这是什么错误,将菱形运算符与通配符一起使用好吗?如果是,那么在哪里?

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

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

将菱形运算符与通配符一起使用好吗?如果是,那么 哪里

不可以。当您使用菱形操作符创建泛型类的新对象时,这意味着您不希望在类型参数上有冗余。它不应与通配符声明的变量组合,该变量没有具体的类型参数

总而言之,你不应该写:

List<?> unknownList = new ArrayList<>();
List unknownList=new ArrayList();
只有当类型确实不重要时,才应使用通配符
。特别是,如果要将项目添加到列表中,请不要使用通配符,因为添加项目意味着您知道要添加的类型


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

您的错误是您有一个类型为
List
的变量,您正在对其调用
add
,并传递一个
字符串

如果变量的类型为
List
,则可以这样做,但由于它只是
List
类型,编译器无法知道向变量引用的任何列表添加
字符串是否合法

如果要存储字符串,请确保有一个类型为
List
(或其他字符串集合)的变量来存储它们

使用diamond操作符创建一些存储在类型中带有通配符的变量中的内容是非常好的。菱形操作符对您在运行时得到的结果没有影响;在运行时,没有类型参数。对所创建对象执行的任何后续操作都将在编译时根据变量类型进行检查,而不是根据用于创建对象的代码行进行检查

但是ArrayList创建的是哪种类型

它可以是
ArrayList
。它可以是
ArrayList
。它可以是
ArrayList
。这真的不重要,因为它们之间的编译代码没有任何区别,而且您得到的只是一个
列表
,因此您无法假设类型参数是什么

将菱形运算符与通配符一起使用好吗


没有。对新创建的泛型对象使用通配符参数化引用是没有意义的。

没有不同类型的
ArrayList
供其创建。类型参数只在编译时存在。您并没有真正回答这个问题(将菱形运算符与通配符一起使用是否好),您只是在解释一般通配符和泛型。。