为什么EnumSet有很多重载的"方法"?

mus*_*ibs 33 java collections enumset

在浏览EnumSet<E> of方法时,我看到了多个of方法的重载实现:

public static <E extends Enum<E>> EnumSet<E> of(E e)

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2)

.
.

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)
Run Code Online (Sandbox Code Playgroud)

然后用另一个重载方法 varargs

public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
    EnumSet<E> result = noneOf(first.getDeclaringClass());
    result.add(first);
    for (E e : rest)
        result.add(e);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

当这个varargs可以处理其他实现时,为什么这个方法会以这种方式重载?这有什么具体原因吗?

我曾经历过同样的Javadoc,但我找不到任何令人信服的解释.

dur*_*597 29

Varargs方法创建一个数组.

public static void foo(Object... args) {
  System.out.println(args.length);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为隐式数组创建.EnumSet是一个非常非常快速的类,因此通过创建所有额外的重载,它们可以在前几种情况下跳过数组创建步骤.这尤其正确,因为在许多情况下Enum没有那么多元素,如果它们有,那么EnumSet可能不包含所有元素.

JavadocEnumSet<E> of(E e1, E e2, E e3, E e4, E e5):

创建最初包含指定元素的枚举集.存在此方法的过载以初始化具有一到五个元素的枚举集.提供了使用varargs功能的第六次重载.这种重载可用于创建最初包含任意数量元素的枚举集,但可能比不使用varargs的重载运行得慢.


Evg*_*eev 8

varags创建一个数组,就在我们打电话的时候

void x(int...x) {...}
..
x(1);
Run Code Online (Sandbox Code Playgroud)

编译器用以下代码替换最后一行:

x(new int[] {1});
Run Code Online (Sandbox Code Playgroud)

如果我们有一个带有1个arg的重载方法,它将不会发生:

void x(int...x) {...}
void x(int x) {...}
Run Code Online (Sandbox Code Playgroud)

然后编译器将选择第二种方法.


Dra*_*vic 7

因为那个班级是由Josh Bloch设计的,那个人知道事情是如何运作的.:)除了创建数组之外,varargs方法还包含循环,这对JIT来说更有效,可以优化代码.

例如,如果我们查看带有五个参数的重载版本的实现:

result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
result.add(e5);
Run Code Online (Sandbox Code Playgroud)

我们注意到它是某种已经展开的循环,看起来像:

for (E e : Arrays.asList(e1, e2, e3, e4, e5)) {
   result.add(e);
}
Run Code Online (Sandbox Code Playgroud)

此外,更短更简单的方法比更长和更复杂的方法更有可能被内联.


小智 6

来自javadoc:

存在此方法的过载以初始化具有一到五个元素的枚举集.提供了使用varargs功能的第六次重载.这种重载可用于创建最初包含任意数量元素的枚举集,但可能比不使用varargs的重载运行得慢.