首页 文章

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

提问于
浏览
38

我只是看着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 回答

  • 39

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

    消息来源的评论说:

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

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

  • 4

    还有一个表现原因 . 每次调用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%的案例中,性能得到了很好的提升 . 不同的是,平均案例表现上升 .

  • 13

    除了这里的其他重要答案之外,还有一个微妙的运行时性能优势(除了避免数组分配),这是零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);
        }
    }
    

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

相关问题