Java列表toArray(T[]a)实现
我正在查看列表界面中定义的方法: 按正确顺序返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回其中。否则,将使用指定数组的运行时类型和此列表的大小分配一个新数组。 如果列表适合指定的数组,且有空闲空间(即数组中的元素多于列表),则紧跟在集合结束后的数组中的元素将设置为null。仅当调用方知道列表不包含任何空元素时,这在确定列表长度时才有用Java列表toArray(T[]a)实现,java,list,generics,toarray,Java,List,Generics,Toarray,我正在查看列表界面中定义的方法: 按正确顺序返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回其中。否则,将使用指定数组的运行时类型和此列表的大小分配一个新数组。 如果列表适合指定的数组,且有空闲空间(即数组中的元素多于列表),则紧跟在集合结束后的数组中的元素将设置为null。仅当调用方知道列表不包含任何空元素时,这在确定列表长度时才有用 <T> T[] toArray(T[] a); T[]toArray(T[]a); 我
<T> T[] toArray(T[] a);
T[]toArray(T[]a);
我只是想知道为什么它是这样实现的,基本上如果你给它传递一个长度<的数组到list.size(),它只会创建一个新的数组并返回它。因此,在方法参数中创建新的数组对象是无用的
此外,如果您使用列表的大小将数组传递给它足够长的时间,则if返回的对象与该对象相同-实际上返回它没有意义,因为它是相同的对象,但为了清晰起见,可以
问题是,我认为这会导致代码效率稍低,我认为toArray应该只接收类并返回包含内容的新数组
没有这样编码的原因是什么?这很可能是为了允许您重用阵列,因此您基本上可以避免(相对昂贵的)某些用例的阵列分配。另一个小得多的好处是调用方可以稍微更有效地实例化数组,因为toArray()必须使用“java.lang.reflect.array.newInstance”方法{
357 public <T> T[] toArray(T[] a) {
358 if (a.length < size)
359 // Make a new array of a's runtime type, but my contents:
360 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
361 System.arraycopy(elementData, 0, a, 0, size);
362 if (a.length > size)
363 a[size] = null;
364 return a;
365 }
358如果(a.长度<尺寸)
359//创建a的运行时类型的新数组,但我的内容:
360 return(T[])array.copyOf(elementData,size,a.getClass());
361系统阵列副本(elementData,0,a,0,大小);
362如果(a.长度>尺寸)
363 a[尺寸]=零;
364返回a;
365 }
也许它有一个运行时类型
从维基:
因此,实例化Java
参数化类型的类为
不可能,因为实例化
需要调用构造函数,
如果类型为,则不可用
不知道
正如其他人提到的,有两个不同的原因:
- 您需要以某种方式传入类型,传入指定类型的数组并不是一种不合理的方式。诚然,为了提高速度,如果在类中也传递了您想要的类型的版本,这可能会很好
- 如果要重用阵列,可以继续传递相同的阵列,而无需每次都创建一个新阵列。这可以节省时间和内存,如果需要多次执行,还可以解决GC问题
Object[] generic_array = { "string" };
String[] strings_array = generic_array; // ClassCastException
看起来效率更高的List.toArray()
就是这样做的,它创建了一个通用的对象
数组
在Java泛型之前,执行类型安全传输的唯一方法是使用以下clude:
String[] stronglyTypedArrayFromList ( List strings )
{
return (String[]) strings.toArray( new String[] );
// or another variant
// return (String[]) strings.toArray( new String[ strings.size( ) ] );
}
谢天谢地,仿制药使这种诡计过时了。保留此方法是为了提供与1.5之前版本代码的向后兼容性。我的猜测是,如果您在调用
toArray(T[])时已经知道T
的具体类型,只声明一个数组比为您调用列表实现Arrays.newInstance()
更有效,而且在许多情况下,您可以重复使用该数组
但是,如果它让您烦恼,那么编写一个实用方法就足够简单了:
public static <E> E[] ToArray(Collection<E> c, Class<E> componentType) {
E[] array = (E[]) Array.newInstance(componentType, c.size());
return c.toArray(array);
}
publicstatice[]ToArray(集合c,类componentType){
E[]数组=(E[])array.newInstance(componentType,c.size());
返回c.toArray(数组);
}
(请注意,无法将E[]写入数组(集合c)
,因为没有Class
对象,无法在运行时创建E
数组,也无法在运行时为E
获取Class
对象,因为泛型已被删除。)您认为效率低下的具体原因是什么?如果您向它传递一个大小为私有静态final T[]=new T[0]
并在数组大小未知时使用它,仍然没有理由不只是传递一个类参数并使用它来代替.getClass()。但是如果有人传递一个数组