2010-09-17 70 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檢查)對大多數調用來說都不會有問題,但它仍然沒有必要,因爲每次優化都可能只有方法重載,並且編譯器總是知道要調用哪個超載。客戶端代碼沒有任何負擔,所以這是一個簡單的勝利。

相關問題