Java - 为何alibaba开发手册强制要求集合转数组用带参的toArray?
一. 运用场景
当我们需要将集合转化为数组的时候,就需要用到集合的toArray()
方法。toArray()
用两个重载方法,其结构如下:
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
1.1 无参toArray()的不可行性。
我们先来看下不带参数的toArray()
:
@Test
public void testToArray() {
ArrayList<java.lang.String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
// 不带参数的toArray方法,返回类型是Object[],需要强转为String。
String[] arr1 = (String[]) list.toArray();
for (String s : arr1) {
System.out.println(s);
}
}
输出结果为:
可见,如果我们通过无参的toArray()
方法,将集合转为数组,但是希望直接对原集合中的元素类型做对应的类型操作,显然是不允许的,因为Object
类型的数组无法强转。
一个类型能否向上转型(强转)关键是看该变量所指向对象与目标类型是否存在继承关系,如果存在则可以强转。
单个Object类型是可以进行强转的,因为Object类型是所有类型的父类,但是对于Object[]类型的数组,显然其并不是String[]类型的父类。因此不能强转。
1.2 toArray(T[] a)的注意点
再来观察toArray(T[] a)
方法:
public <T> T[] toArray(T[] a) {
// size指的是集合的元素个数,a.length则是我们传入的参数:数组的长度。
if (a.length < size)
// 重新分配内存空间,并返回一个新的数组地址
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
// 如果传入指定的数组大小 超过了 集合元素的大小
if (a.length > size)
// 可见,多余的部分将会变成null
a[size] = null;
return a;
}
可以发现,若数组元素 > 实际所需,下标为list.size()
的元素会变成null
,因此我们应该对目标数组的大小作出规范,做到:集合有多少个元素,转成的数组就有多少个元素。
案例如下:
数组元素 > 实际所需
@Test
public void testToArray() {
ArrayList<java.lang.String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
String[] arr2 = list.toArray(new String[5]);
for (String s : arr2) {
System.out.println(s);
}
}
代码运行为:
正确写法:
@Test
public void testToArray() {
ArrayList<java.lang.String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
String[] arr2 = list.toArray(new String[list.size()]);
for (String s : arr2) {
System.out.println(s);
}
}