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

时间:2010-09-17 18:18:16

标签: java guava overloading

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

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

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

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

3 个答案:

答案 0 :(得分:39)

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

消息来源的评论说:

  

这些最多可达11个。之后,您只需获得varargs表单,以及可能出现的任何警告。 :(

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

答案 1 :(得分:13)

还有一个表现原因。每次调用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 );

在95%的案例中带来了良好的性能提升。不同的是,平均案例表现上升。

答案 2 :(得分:4)

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

如果我们没有单独的方法重载,并且只包含一个基于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);
    }
}

对于大多数调用来说,switch case(或if-else check)的性能不会很糟糕,但它仍然是不必要的,因为每个优化只能有方法重载,并且编译器总是知道哪个超载来调用。客户端代码没有任何负担,因此很容易获胜。