2010-09-17 60 views
38

我只是看着番石榴的ImmutableList,我注意到of()方法重载了12次。为什么Guava的ImmutableList有很多重载的()方法?

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

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

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

+5

无论如何,它们都将参数传递给内部可变参数方法......呵呵。我将不得不在这个问题上扬眉吐气。嗯,源代码有一个评论:“这些会上升到十一点,之后,你只要得到可变参数表单,并且可能会出现任何警告。”“我不确定它指的是什么警告。 – 2010-09-17 18:22:41

+0

@Tim,这可能会是一个很好的答案,至少值得赞赏,并且可能是被接受的答案。 – jjnguy 2010-09-17 18:34:12

+7

+1 for Google for going to eleven! – romacafe 2010-09-17 18:54:39

回答

39

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

源代码中的注释说:

这些上升到十一点。之后,您只需获得可变参数表格,并且可能会随附任何警告。 :(

注意的Java 7的@SafeVarargs注解是专门添加,以消除这种事情的需要。可以使用单个of(E...)@SafeVarargs注解,并不会与通用的参数给予警告。

+0

嗨,你能否更新你的答案以反映@Rinke引用的性能部分?我认为这值得一提。 – 2016-08-25 22:36:28

+2

@JoãoRebelo:虽然这不是真的,但方法只是马上去调用可变参数方法。 – ColinD 2016-08-26 17:31:19

+0

你的意思是在这个特定的情况下?或者我误解你的意思? – 2016-08-28 21:41:00

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%的情况下,

可以带来很好的性能提升。不同的是,案件的平均表现上升。

+6

注意:虽然这个原则是成立的,但我刚刚从ColinD那里了解到,番石榴实际上并不是这样,因为无论如何(在当前的实现中),重载的方法会导致varargs调用。 – Rinke 2016-09-01 10:14:50

4

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

如果我们没有对这些不同的方法重载,只包括一个基于可变参数法,则该方法会是这个样子:

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); 
    } 
} 

开关罩的性能(或者,如果-else检查)对大多数调用来说都不会有问题,但它仍然没有必要,因为每次优化都可能只有方法重载,并且编译器总是知道要调用哪个超载。客户端代码没有任何负担,所以这是一个简单的胜利。

相关问题