List.of(E e1, E e2, E e3) 与 List.of(E... elements) 有什么区别

问题描述 投票:0回答:1

List.of(E e1, E e2, E e3) 返回 ImmutableCollections.ListN(e1, e2, e3);

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

和 List.of(E... elements) 也返回 ImmutableCollections.ListN(elements)

@SafeVarargs
@SuppressWarnings("varargs")
static <E> List<E> of(E... elements) {
    switch (elements.length) { // implicit null check of elements
        case 0:
            return ImmutableCollections.emptyList();
        case 1:
            return new ImmutableCollections.List12<>(elements[0]);
        case 2:
            return new ImmutableCollections.List12<>(elements[0], elements[1]);
        default:
            return new ImmutableCollections.ListN<>(elements);
    }
}

和 ImmutableCollections.ListN<> 构造函数

@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;
}

我之前注意到 List.of(E... elements) 的性能较差,因为它使用可变参数。 因此创建了诸如 List.of(E e1, E e2, E e3) 之类的重载版本,以便不在内部创建数组。

但是,经证实,重载版本在调用ListN时也会在内部创建一个数组,该数组接收变量参数作为参数。

那么,为什么会创建一个List大小大于3的重载版本呢?

java variadic-functions
1个回答
0
投票

从技术上讲,函数

List.of(E... elements)
可以处理任意数量的输入元素。但是,输入可以是数组,并且调用者拥有对输入数组的引用。调用者可以在构造不可变列表时更新数组,从而导致不一致。这称为“检查时间到使用时间”(TOCTOU)。为了避免 TOCTOC,Java 必须复制输入数组,这会降低性能。具有特定数量输入参数的重载函数不存在 TOCTOU 问题,不需要复制,因此性能更好。

© www.soinside.com 2019 - 2024. All rights reserved.