问题描述
ArrayList提供了两个toArray()函数:
Object[] toArray()
<T> T[] toArray(T[] a)
通常如果将ArrayList转换成array通常都是都是使用第二种方式,因为第一种方式如果进行强制类型转换会造成java.lang.ClassCastException
,因为它返回的是Object[]
,但是Java在合法的情况下是支持父类转子类的,为什么会出现这种情况?
比如下面这样明显是合法的:
Object x = new Integer(0);
System.out.println((Integer) x);
p.s: 对于上面问题我知道正确的做法是下面这样:
String[] y = x.toArray(new String[0]);
只是不知道为什么不支持强制类型转换?
String[] y = (String[]) x.toArray()
报错信息
List<String> x = new ArrayList<String>();
x.add("sherlock");
String[] y = (String[]) x.toArray();
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
...
参考资料
get源代码
参考在ArrayList中get
的源代码,elementData是一个Object数组,却可以强制类型转换成E:
111 private transient Object[] elementData;
336 @SuppressWarnings("unchecked")
337 E elementData(int index) {
338 return (E) elementData[index];
339 }
348 public E get(int index) {
349 rangeCheck(index);
350
351 return elementData(index);
352 }
toArray()源代码
295 public Object[] toArray() {
296 return Arrays.copyOf(elementData, size);
297 }
toArray(T[] a)源代码
(T[]) Arrays.copyOf(elementData, size, a.getClass());
也是一个强制类型转换。
323 @SuppressWarnings("unchecked")
324 public <T> T[] toArray(T[] a) {
325 if (a.length < size)
326 // Make a new array of a's runtime type, but my contents:
327 return (T[]) Arrays.copyOf(elementData, size, a.getClass());
328 System.arraycopy(elementData, 0, a, 0, size);
329 if (a.length > size)
330 a[size] = null;
331 return a;
332 }
ClassCastException
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. For example, the following code generates a ClassCastException
:
Object x = new Integer(0);
System.out.println((String) x);
答案
参考@kevinz :
2745 public static <T> T[] copyOf(T[] original, int newLength) {
2746 return (T[]) copyOf(original, newLength, original.getClass());
2747 }
2771 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772 T[] copy = ((Object)newType == (Object)Object[].class)
2773 ? (T[]) new Object[newLength]
2774 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775 System.arraycopy(original, 0, copy, 0,
2776 Math.min(original.length, newLength));
2777 return copy;
2778 }
Object[] toArray()对应的是(T[]) new Object[newLength]
,这里T
就是Object
。
<T> T[] toArray(T[] a)对应的是(T[]) Array.newInstance(newType.getComponentType(), newLength)
,这里T
就是String
。
(T[]) Arrays.copyOf(elementData, size, a.getClass());
强转可以成功是因为数组的类型本身就为a.getClass()
。通过
Array.newInstance(newType.getComponentType(), newLength)
创建的(目标类型)数组对象。String[] y = (String[]) x.toArray()
无法强制转换是因为array
的数据类型为Object[]
而不是String[]
。