Java泛型集合的toArray方法
最近在使用泛型集合中的toArray(T[] a)
方法时出现了一些问题,现记录下来。
大家可以先考虑一下下面这段代码的正确性:
List<Integer> res = new ArrayList<>();
int[] a = res.toArray(new int[0]);
有的朋友可能会觉得上面这段代码没什么问题,可以编译通过;有的朋友可能一眼就看出了问题,说:toArray()
传入的参数类型不对,不能为基本类型!
的确,上面这段代码不能编译通过,在IDEA中会报错:
原因是:
toArray(T[] a)
声明中的T
指的是泛型类型,它只能是引用类型,所以参数必须是一个引用类型的数组,而int[]
是基本类型数组,当然会报错了。
何为引用类型?我们知道,一个类的名字可以用来作为一种类型,当我们用类名来声明一个变量的时候,这个变量会包含对这个类对象的一个引用,而不是直接包含这个类对象。因为我们用类名声明了对类对象的引用,所以把类类型称为“引用类型”。同样,Java还把接口(Interface)、数组类型(array)当成引用类型。
我们再来看看下面这段代码,考虑它的正确性:
List<int[]> res = new ArrayList<>();
int[][] a = res.toArray(new int[0][]);
有的朋友可能会觉得第一行代码就出错了,int
类型是基本类型,不能用来创建泛型数组!
如果你也觉得第一行代码有错,不妨看一下上面对引用类型的介绍。正如上面所说,Java会把数组当成对象,数组类型是引用类型,所以第一行代码没有错,可以编译通过。
对于第二行代码,有的朋友可能会说,第一个例子int[] a = res.toArray(new int[0]);
不就报错了吗,这里同样是基本类型数组,肯定也会报错;有的朋友可能会说,你这传入的是二维数组,而方法定义的参数是一维数组,肯定会报错。
结果是什么呢?我们跑一下这段代码:
List<int[]> res = new ArrayList<>();
res.add(new int[]{100});
int[][] a = res.toArray(new int[0][]);
System.out.println(a[0][0]);
//成功运行并输出
100
Process finished with exit code 0
结果能编译通过!原因在于:
- Java里没有多维数组!
int[][]
实际上是一个元素是一维数组的数组;
int[3][2] 实际上是 int[3] {int[2], int[2], int[2]}
- 如上面所说,数组类型是引用类型,所以
int[][]
是一个引用类型数组,即toArray(T[] a)
里的T
是int[]
。
那么,Java为什么不支持多维数组呢?这个问题留给读者们思考。