ArrayList源码的 elementData.getClass() != Object[].class

1. 放出源码

2.  elementData与Object[]

  elementData的定义如下

transient Object[] elementData; // non-private to simplify nested class access

  请看如下代码

package test;

public class UserTest2 {
    public static void main(String[] args) {
        User[] users = new User[]{
                new User(1, "admin", "[email protected]"),
                new User(2, "maco", "[email protected]"),
                new User(3, "kitty", "[email protected]")
        };

        Object[] target = users;
        System.out.println(target.getClass());  // class [Ltest.User;
        target[0] = new Object();   // java.lang.ArrayStoreException: java.lang.Object
    }
}

  显然直接将非Object[]类型数组赋予Object[]类型, 相当于将子类对象赋予父类变量, 这会导致什么问题呢,请看如下代码

List<Object> list = new ArrayList<>(Arrays.asList("room", "take"));
System.out.println(list.getClass());
list.set(0, new Object());

  Arrays.asList("room", "take")返回的类型是String[](后面会解释, 注意这个BUG早就被修复了), 上面的代码显然会出错, 且错得莫名其妙, 我定义Object[]还不能存储Object实例了,显然是个BUG

public class UserTest {
    public static void main(String[] args) {
        User[] users = new User[]{
                new User(1, "admin", "[email protected]"),
                new User(2, "maco", "[email protected]"),
                new User(3, "kitty", "[email protected]")
        };

        Object[] objects = users;
        System.out.println(objects.getClass());         // class [Ltest.User;
        if(objects.getClass() != Object[].class){
            objects = Arrays.copyOf(objects, objects.length, Object[].class);   // class [Ljava.lang.Object;
        }
        System.out.println(objects.getClass());
    }
}

  如上代码可知, 经过copyOf之后, 返回的类型是Object[], 就不会出现上述所说的错误了

3. Arrays.asList干了什么?

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

  其调用的ArrayList不是java.util.ArrayList, 而是其内部类

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }    
        // BUG实现
        @Override
        public Object[] toArray() {
            return a.clone();
        }
    
        
        // jdk-13.0.1的实现
       /*
        @Override
        public Object[] toArray() {
            return Arrays.copyOf(a, a.length, Object[].class);
        }
        */

  可运行以下代码测试

System.out.println(new String[]{}.clone().getClass());  // class [Ljava.lang.String;

4. Arrays.copyOf做了什么

    @SuppressWarnings("unchecked")
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

    @HotSpotIntrinsicCandidate
    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;
    }
        Class newType = Object[].class;
        System.out.println(newType.getComponentType());     // class java.lang.Object

  数组的class对象的getComponentType()返回其元素组成类型, System.arraycopy进行数组复制(浅复制,复制引用)

public static void main(String[] args) {
        User[] users = new User[]{
                new User(1, "admin", "[email protected]"),
                new User(2, "maco", "[email protected]"),
                new User(3, "kitty", "[email protected]")
        };

        Object[] objects = users;
        System.out.println(objects.getClass());     // class [Ltest.User;
        objects = new Object[users.length];
        System.arraycopy(users, 0, objects, 0, Math.min(users.length, objects.length));
        System.out.println(objects.getClass());     // class [Ljava.lang.Object;
        System.out.println(objects[0] == users[0]); // true
    }

 5. 参考

6.

猜你喜欢

转载自www.cnblogs.com/chenxingyang/p/11960038.html