泛型 - ArrayList中toArray()为什么不支持强制类型转换?[Java]

查看:101
本文介绍了泛型 - ArrayList中toArray()为什么不支持强制类型转换?[Java]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

问题描述

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()

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

通过Array.newInstance(newType.getComponentType(), newLength)创建的(目标类型)数组对象。


String[] y = (String[]) x.toArray()无法强制转换是因为array的数据类型为Object[]而不是String[]

这篇关于泛型 - ArrayList中toArray()为什么不支持强制类型转换?[Java]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆