今天发现一段源码,大概是这个样子的:

1
2
3
List<Method> methods = new ArrayList();
......
return methods.toArray(new Method[0]);

我明白大致意思应该是要通过一个Collection集合返回一个Method类型的数,但是下面的几个问题不禁让我思考。

为什么要传入一个new Method[0]这样长度为0的数组

Collection类中有两个 toArray 方法

1
2
Object[] toArray();
<T> T[] toArray(T[] a);

从方法签名可以看出第一个方法是返回Object类型的数组,而第二个方法返回泛型数组。

也就是说 T[] a 的作用仅仅是规定返回类型?

如果只是返回泛型的话为什么不直接 <T> T[] toArray(Class<T> clazz);

先查看ArrayList的源码:

1
2
3
4
5
6
7
8
9
10
11
public <T> T[] toArray(T[] a) {
// a的长度不足集合中数据的长度
if (a.length < size)
// 将 elementData 复制到一个类型为 a.getClass 的泛型数组
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
// a的长度组够长,则将 elementDate 复制到 a 中,并返回
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

原来这个方法还能将数据传入指定数组中。

而当数组长度不够时,这个方法的作用仅仅是返回一个泛型数组。因此传入一个 new Method[0] 仅仅是规定了泛型,而且长度为0的数组还能够节省空间。

解决了这个问题,不禁又想到另一个问题。

Object[] toArray() 为什么不返回泛型

ArrayList 未传入泛型时,无法确定 elementData 数组的类型,从而无法定义数组,因此 ArrayList 中的 elementData 只能为 Object 类型的数组。

Object 类型的数据可以直接强转为 泛型 T,但是 Object[] 数组却无法直接强转为泛型 T[] 数组。

ArrayList 中的 toArray 方法并没有对 Object[] 数组做特殊处理,而是直接复制一份Object数组返回给我们,让我们自己对数组进行处理。