ArrayList c.toArray might (incorrectly) not return Object[] (see 6260652)

bug库链接

  • 问题主要是下面这么一段c.toArray might (incorrectly) not return Object[] (see 6260652)
  • 翻译过来的话就是toArray返回的数组的类型不一定是Object[]的
 public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
  • 我们看bug库的标题是JDK-6260652 : (coll) Arrays.asList(x).toArray().getClass() should be Object[].class
  • 可是我们看下面这一段代码
public static void test1(){
        List<String> list = new java.util.ArrayList<String>(Arrays.asList("123"));
        //class java.util.ArrayList
        Object[] listArray = list.toArray();
        System.out.println(listArray.getClass());//class [Ljava.lang.Object;
        listArray[0] = new Object();
}
public static void test2(){
        List<String> list = Arrays.asList("123");// class java.util.Arrays$ArrayList
        Object[] objArray = list.toArray();
        System.out.println(objArray.getClass());  // class [Ljava.lang.String;
        objArray[0] = new Object(); // cause ArrayStoreException
}
  • test2()的list.toArray().getClass()却不是Obeject[].class了
  • 接下来我们来看一下toAarry的实现
Arrays$ArrayList toArray的实现
public Object[] toArray() {
    return (Object[])this.a.clone();
}
ArrayList toArray的实现
public Object[] toArray() {
    return Arrays.copyOf(this.elementData, this.size);
}
  • 这里看没问题呀,返回的类型都是Object[],可是getClass的结果为什么会出现差异。
  • 其实原因是:toArray 方法返回的是 Object[],但是与 java.util.ArrayList 不同的是这里底层存储是泛型类型的数组private final E[] a,所以保留了实际的类型。
public static void test() {
    Object[] objs = new String[1]; //Arrays$ArrayList toArray的实现类型这个过程
    System.out.println( objs.getClass() ); //class [Ljava.lang.String;
    Object[] objs2 = new Object[1];//ArrayList toArray的实现类型这个过程
    objs2[0] = new String();
    System.out.println( objs2.getClass() ); //class [Ljava.lang.Object;
}
这样看更加直观
#Array.toList()实现#
public static void test4(){
    String[] strings = {new String(),new String()};  //private final E[] a
    Object[] objects = (Object[]) strings.clone(); //return (Object[])this.a.clone();
    System.out.println(objects.getClass()); //class [Ljava.lang.String;
}

猜你喜欢

转载自blog.csdn.net/viscu/article/details/80313028