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



在检查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)

然后是另一个重载方法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;
}

当这个变量可以处理其他实现时,为什么这个方法以这种方式重载?这有什么特别的原因吗?

我已经看了相同的Javadoc,但我找不到任何令人信服的解释

Varargs方法创建一个数组。

public static void foo(Object... args) {
  System.out.println(args.length);
}

可以工作,因为隐式创建了数组。EnumSet是一个设计得非常非常快的类,所以通过创建所有额外的重载,它们可以在前几个情况下跳过数组创建步骤。特别是在很多情况下,Enum没有那么多的元素,即使有,EnumSet也可能不包含所有的元素。

Javadoc for EnumSet<E> of(E e1, E e2, E e3, E e4, E e5):

创建一个初始包含指定元素的enum集合。存在此方法的重载,用于初始化包含1到5个元素的枚举集合。提供了使用varargs特性的第六种重载。此重载可用于创建初始包含任意数量元素的枚举集,但可能比不使用变量的重载运行速度慢。

varags创建一个数组,这时我们调用

void x(int...x) {...}
..
x(1);

编译器将最后一行替换为:

x(new int[] {1});

如果我们有一个带有1个参数的重载方法,则不会发生这种情况:

void x(int...x) {...}
void x(int x) {...}

编译器将选择第二种方法

因为这个类是由Josh Bloch设计的,他知道事情是如何运作的。:)除了创建数组之外,varargs方法还包含循环,JIT优化代码的工作更多。

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

result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
result.add(e5);

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

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

同时,较短、较简单的方法比较长、较复杂的方法更容易被内联。

From javadoc:

存在该方法的重载,用于初始化带有的枚举集合一到五种元素。提供第六种重载使用变量特性。此重载可用于创建一种枚举集合,最初包含任意数量的元素,但是可能比不使用变量的重载运行得慢。

相关内容

  • 没有找到相关文章

最新更新