为什么Guava的ImmutableList有这么多重载的()方法?

时间:2022-11-15 00:05:16

I was just looking at Guava's ImmutableList and I noticed that the of() method was overloaded 12 times.

我只是看着Guava的ImmutableList,我注意到of()方法被重载了12次。

It looks to me that all they needed was:

在我看来,他们所需要的只是:

static <E> ImmutableList<E> of();
static <E> ImmutableList<E> of(E element); // not even necessary
static <E> ImmutableList<E> of(E... elements);

What's the reason for having so many similar variations?

有这么多类似变化的原因是什么?

3 个解决方案

#1


39  

Varargs and generics do not play nicely together. Varargs methods can cause a warning with generic arguments, and the overloads prevent that warning except in the rare case that you want to add more than 11 items to the immutable list using of().

Varargs和泛型不能很好地融合在一起。 Varargs方法可以使用泛型参数引发警告,并且重载会阻止该警告,除非在极少数情况下您要使用()将超过11个项添加到不可变列表中。

The comments in the source say:

消息来源的评论说:

These go up to eleven. After that, you just get the varargs form, and whatever warnings might come along with it. :(

这些最多可达11个。在那之后,你只需要获得varargs表格,以及随之而来的任何警告。 :(

Note that Java 7's @SafeVarargs annotation was added specifically to eliminate the need for this sort of thing. A single of(E...) method annotated with @SafeVarargs could be used and would not give warnings with generic arguments.

请注意,Java 7的@SafeVarargs注释是专门添加的,以消除对此类事物的需求。可以使用带有@SafeVarargs注释的单个(E ...)方法,并且不会使用泛型参数发出警告。

#2


13  

There's also a performance reason. Every invocation of a varargs method causes an array allocation and initialization. If you have somehow determined that e.g. 95% of the calls are with 3 or less arguments and only 5% with 4 or more, then overloading like this

还有一个表现原因。每次调用varargs方法都会导致数组分配和初始化。如果你以某种方式确定了95%的调用具有3个或更少的参数,只有5%具有4个或更多,然后像这样重载

public static <E> ImmutableList<E> of();
public static <E> ImmutableList<E> of( E e );
public static <E> ImmutableList<E> of( E e1, E e2 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3, E... es );

leads to a nice performance boost in 95% of the cases. Differently put, the average case performance goes up.

在95%的案例中,性能得到了很好的提升。不同的是,平均案例表现上升。

#3


4  

In addition to the other great answers here, there's a subtle runtime performance advantage (in addition to avoiding the array allocation), which is that the zero-arg and single-arg overloads return implementations that are optimized for representing empty and single-instances lists (respectively).

除了这里的其他重要答案之外,还有一个微妙的运行时性能优势(除了避免数组分配),这是零arg和单arg重载返回为表示空实例和单实例列表而优化的实现(分别)。

If we didn't have separate method overloads for these and only included a single varargs-based method, then that method would look something like this:

如果我们没有单独的方法重载,并且只包含一个基于varargs的方法,那么该方法看起来像这样:

public static <E> ImmutableList<E> of(E... es) {
    switch (es.length) {
      case 0:
        return emptyImmutableList();
      case 1:
        return singletonImmutableList(es[0]);
      default:
        return defaultImmutableList(es);
    }
}

The performance of the switch case (or if-else checks) wouldn't be bad for most calls, but it's still unnecessary since can just have method overloads for each optimization, and the compiler always knows which overload to call. There's no burden placed on the client code, so it's an easy win.

切换情况(或if-else检查)的性能对于大多数调用来说并不是坏事,但它仍然是不必要的,因为每次优化都可能有方法重载,并且编译器总是知道调用哪个重载。客户端代码没有任何负担,所以这很容易获胜。

#1


39  

Varargs and generics do not play nicely together. Varargs methods can cause a warning with generic arguments, and the overloads prevent that warning except in the rare case that you want to add more than 11 items to the immutable list using of().

Varargs和泛型不能很好地融合在一起。 Varargs方法可以使用泛型参数引发警告,并且重载会阻止该警告,除非在极少数情况下您要使用()将超过11个项添加到不可变列表中。

The comments in the source say:

消息来源的评论说:

These go up to eleven. After that, you just get the varargs form, and whatever warnings might come along with it. :(

这些最多可达11个。在那之后,你只需要获得varargs表格,以及随之而来的任何警告。 :(

Note that Java 7's @SafeVarargs annotation was added specifically to eliminate the need for this sort of thing. A single of(E...) method annotated with @SafeVarargs could be used and would not give warnings with generic arguments.

请注意,Java 7的@SafeVarargs注释是专门添加的,以消除对此类事物的需求。可以使用带有@SafeVarargs注释的单个(E ...)方法,并且不会使用泛型参数发出警告。

#2


13  

There's also a performance reason. Every invocation of a varargs method causes an array allocation and initialization. If you have somehow determined that e.g. 95% of the calls are with 3 or less arguments and only 5% with 4 or more, then overloading like this

还有一个表现原因。每次调用varargs方法都会导致数组分配和初始化。如果你以某种方式确定了95%的调用具有3个或更少的参数,只有5%具有4个或更多,然后像这样重载

public static <E> ImmutableList<E> of();
public static <E> ImmutableList<E> of( E e );
public static <E> ImmutableList<E> of( E e1, E e2 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3, E... es );

leads to a nice performance boost in 95% of the cases. Differently put, the average case performance goes up.

在95%的案例中,性能得到了很好的提升。不同的是,平均案例表现上升。

#3


4  

In addition to the other great answers here, there's a subtle runtime performance advantage (in addition to avoiding the array allocation), which is that the zero-arg and single-arg overloads return implementations that are optimized for representing empty and single-instances lists (respectively).

除了这里的其他重要答案之外,还有一个微妙的运行时性能优势(除了避免数组分配),这是零arg和单arg重载返回为表示空实例和单实例列表而优化的实现(分别)。

If we didn't have separate method overloads for these and only included a single varargs-based method, then that method would look something like this:

如果我们没有单独的方法重载,并且只包含一个基于varargs的方法,那么该方法看起来像这样:

public static <E> ImmutableList<E> of(E... es) {
    switch (es.length) {
      case 0:
        return emptyImmutableList();
      case 1:
        return singletonImmutableList(es[0]);
      default:
        return defaultImmutableList(es);
    }
}

The performance of the switch case (or if-else checks) wouldn't be bad for most calls, but it's still unnecessary since can just have method overloads for each optimization, and the compiler always knows which overload to call. There's no burden placed on the client code, so it's an easy win.

切换情况(或if-else检查)的性能对于大多数调用来说并不是坏事,但它仍然是不必要的,因为每次优化都可能有方法重载,并且编译器总是知道调用哪个重载。客户端代码没有任何负担,所以这很容易获胜。