toArray()和toArray(T[ ] a)的比较
两者的功能都是 : 返回一个数组,包含此向量中以恰当顺序存放的所有元素
很明显两个方法的参数不同.那么对于toArray(T[ ] a)中的参数数组的作用是什么呢?
通过源码来分析
toArray()源码
protected Object[] elementData;
public synchronized Object[] toArray() {
return Arrays.copyOf(elementData, elementCount);
}
调用Arrays.copyOf(T[] original, int newLength)
public static <T> T[] copyOf(T[] original, int newLength) {
// 其中original.getClass() : class [Ljava.lang.Object;
return (T[]) copyOf(original, newLength, original.getClass());
}
继续调用copyOf(U[ ] original, int newLength, Class<? extends T[ ]> newType)
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class) // true
? (T[]) new Object[newLength] // 直接new一个新的Object类型的数组,长度为原向量的长度
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
结论 : 通过分析,若使用无参的copyOf()方法,那么只会得到Object类型的数组,强转类型的话将会报错 : java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
toArray(T[ ] a)源码
public synchronized <T> T[] toArray(T[] a) {
// 当创建的数组的长度小于向量集的大小,则直接通过Arrays方法进行复制
// 但这样会新建一个数组T[]
if (a.length < elementCount)
return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());
// 创建的数组长度大于向量集的大小
System.arraycopy(elementData, 0, a, 0, elementCount); // 先将向量集中的元素复制到创建的数组中
// 若创建的数组的大小刚好和向量集大小相同,则直接返回复制好的数组a.
return a;
}
对于上面有三种可能,然而最好的情况是创建一个想要的类型,并且创建的数组大小刚好等于向量集的大小,这样效率最高!
当a.length < elementCount时,调用下面的方法.
会创建一个和向量集大小相同的新数组.
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class) // false
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
其中newType.getComponentType()解释:(转自:https://blog.csdn.net/claram/article/details/53412256)
- 非数组类型无法通过
getComponentType()
获取到相应的 Class 对象; - 非数组类型无法通过
(String [])Array.newInstance(String[].class.getComponentType(), 10)
方法反射生成数组对象,因为获取不到 Class 对象; - 无论基本数据类型(byte short int long float double char boolean)的数组还是引用数据类型(Integer String 等)的数组,都可以通过
getComponentType()
获取到相应的 Class 对象,都可以通过(String [])Array.newInstance(String[].class.getComponentType(), 10)
方法反射生成数组对象。
上面的方法调用了Array.newInstance(Class<?> componentType, int length)
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
// 创建一个具有指定的组件类型和长度的新数组。
return newArray(componentType, length);
}
继续调用newArray(Class<?> componentType, int length)方法.
该方法使用native关键字修饰1.
private static native Object newArray(Class<?> componentType, int length)
throws NegativeArraySizeException;
当a.length > elementCount时,会将空元素赋值为null。导致白白浪费时间!
// 大于向量集的元素将赋值为null
if (a.length > elementCount)
a[elementCount] = null;
总结 : 因此若创建的数组小于向量集的数组那么将会重新创建一个与创建数组类型相同且数组大小与向量集大小相同的新数组
toArray()和toArray(T[ ] a)代码示例
import java.lang.reflect.Array;
import java.util.*;
public class VectorDemo {
public static void main(String[] args) {
Vector vector = new Vector(20);
vector.addElement("a");
vector.addElement("b");
vector.addElement("c");
vector.addElement("d");
// 返回vector的容量 : 20
System.out.println(vector.capacity());
// 返回vector的实际大小 : 4
System.out.println(vector.size());
// toArray(T[] a)的应用
String[] s = new String[2];
s = (String[]) vector.toArray(s);
System.out.println(Arrays.toString(s));
Object[] obj = vector.toArray();
System.out.println("obj : " + Arrays.toString(obj));
// Exception in thread "main" java.lang.ArrayStoreException
// 试图将错误类型的对象存储到一个对象数组时抛出的异常
// 由于vector中的元素为String类型,强制转换为Interger,类型转换错误!
/*Integer[] arrInt = new Integer[4];
arrInt = (Integer[]) vector.toArray(arrInt);
System.out.println(Arrays.toString(arrInt));*/
// Exception in thread "main" java.lang.ClassCastException:
// [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
/*s = (String[]) vector.toArray();
System.out.println(Arrays.toString(s));*/
}
}
/* 输出结果 :
s : [a, b, c, d]
obj : [a, b, c, d]
*/
根据上面的报错,可以看到想要返回特开的数组类型,需要使用toArray(T[ ] a)方法,其中T[ ] a;数组最好设置的与向量集大小相同,可以这样定义 : String s = new String[vector.size()];
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。 这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。
作者:youjianbo_han_87
原文:https://blog.csdn.net/youjianbo_han_87/article/details/2586375 ↩︎