java11 新特性 3

of 方法与 copyof 方法的区别

var list1 = List.of(“aa”, “bb”, “cc”);
var copy1 = List.copyOf(list1);
System.out.println(list1 == copy1);
// 运行结果: true

var list2 = new ArrayList();
var copy2 = List.copyOf(list2);
System.out.println(list2 == copy2);
// 运行结果: false


**注意:**var也是Java11新推出的特性**局部变量类型推断**,这里面不再赘述。

第一段代码和第二段代码差不多,为什么返回结果不一样呢?我们来看一下他们的源码:

static <E> List<E> of(E e1, E e2, E e3) {
    return new ImmutableCollections.ListN<>(e1, e2, e3);
}

static final class ListN<E> extends AbstractImmutableList<E>
        implements Serializable {

    static final List<?> EMPTY_LIST = new ListN<>();

    @Stable
    private final E[] elements;

    @SafeVarargs
    ListN(E... input) {
        // copy and check manually to avoid TOCTOU
        @SuppressWarnings("unchecked")
        E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
        for (int i = 0; i < input.length; i++) {
            tmp[i] = Objects.requireNonNull(input[I]);
        }
        elements = tmp;
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public int size() {
        return elements.length;
    }

    @Override
    public E get(int index) {
        return elements[index];
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        throw new InvalidObjectException("not serial proxy");
    }

    private Object writeReplace() {
        return new CollSer(CollSer.IMM_LIST, elements);
    }
}[](javascript:void(0); "复制代码")


    static <E> List<E> copyOf(Collection<? extends E> coll) {
        return ImmutableCollections.listCopy(coll);
    }

    static <E> List<E> listCopy(Collection<? extends E> coll) {
        if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {
            return (List<E>)coll;
        } else {
            return (List<E>)List.of(coll.toArray());
        }
    }[](javascript:void(0); "复制代码")


```

从源码可以看出,copyOf 方法会先**判断来源集合是不是 AbstractImmutableList 类型**的,如果是,就直接返回,如果不是,则调用 of 创建一个新的集合。第二段代码因为用的 new 创建的集合,**不属于不可变 AbstractImmutableList 类的子类**,所以 copyOf 方法又创建了一个新的实例,所以为false。

**扩展:**使用Set.of()方法创建Set对象时,**不可以包含重复数据**。