Java 故障初始化列表<;对象[]>;使用Arrays.asList

Java 故障初始化列表<;对象[]>;使用Arrays.asList,java,list,generics,Java,List,Generics,初始化列表时,我可以执行以下操作: List<Object[]> foo = new ArrayList<>(); foo.add(new Object[]{816, "foo", 2.6}); 无法编译,但出现错误: incompatible types: inference variable T has incompatible bounds equality constraints: java.lang.Object[] lower bounds: java.la

初始化列表时,我可以执行以下操作:

List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});
无法编译,但出现错误:

incompatible types: inference variable T has incompatible bounds
equality constraints: java.lang.Object[]
lower bounds: java.lang.Object

为什么它不能正确进行类型推断以及如何解决此问题?

当您将引用类型数组传递给
数组时。asList
将获得该引用类型的
列表


因此,
Arrays.asList(新对象[]{“bar”,286})
返回一个
列表,而不是
列表,如果列表中只有一个元素,
Collections。singletonList(新对象[]{…})
是一个更好的选择,因为它避免了varargs,并使调用站点的行为更加明显。

签名:

public static <T> List<T> asList(T... a)
公共静态列表asList(T…a)
返回类型为
List
。现在你应该问问自己什么是
T

T
对象
,因此返回类型将是
列表
,而不是
列表

您的呼叫:

Arrays.asList(new Object[]{"bar", 286});
对象[]
中创建一个列表。因此,数据被转换成一个新的
列表

So
Arrays.asList(新对象[]{“bar”,286}).get(0)将返回“bar”

在本次通话中:

List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});
如果您有问题,请随时问我:)

当您使用
List bar=Arrays.asList(新对象[]{“bar”,286})你实际上有一个二维数组,你可以通过执行
List bar=Arrays.asList(newobject[]{newobject[]{“bar”,“asd”,123}})来解决这个问题;

记住,
..
只是数组参数的语法糖。您可以使用以下两种方法调用具有可变参数的方法:
foo(Object…

foo("hello", 1);

因为编译器无论如何都要构造第二种形式

由于编译器推断类型时不考虑接收器类型,因此它查看
数组.asList(新对象[]{“bar”,286})
,并认为您的意思是创建
对象的列表,而不是
对象[]
的单一列表

使用现有语法最简单的方法就是添加一个显式类型参数:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});
List bar=Arrays.asList(新对象[]{“bar”,286});
添加
会告诉编译器T应该是什么

或者,如果您不需要列表是可变的:

List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});
List bar=Collections.singletonList(新对象[]{“bar”,286});

问题在于
数组。asList
是一种varargs方法,从技术上讲,它接收包含参数的数组,并且由于与前泛型的兼容性,代码仍然接受数组而不是参数列表。当传递单个数组时,调用是不明确的,将像预varargs方法调用一样进行处理

当您有多个参数时,问题就会消失:

List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}, new Object[]{"baz", 123});
List bar=Arrays.asList(新对象[]{“bar”,286},新对象[]{“baz”,123});
如果只有一个参数,则可以通过插入显式列表元素类型来帮助编译器:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});
List bar=Arrays.asList(新对象[]{“bar”,286});
或者,您可以使用

List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});
List bar=Collections.singletonList(新对象[]{“bar”,286});

创建大小为1的不可变列表。请注意,这不同于
数组。asList
,因为后者返回一个固定大小的列表,但仍然可以通过
set

进行更改,这是一个一般的经验法则,永远不要混合使用泛型和数组。(一旦你理解了为什么这是一条好的经验法则,你就可以忽略这条规则。)
List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}, new Object[]{"baz", 123});
List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});
List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});