2016-03-15 68 views
7

我正在將Java7代碼移植到Java8,並提出了以下問題。 在我的代碼庫,我有兩個方法:對通用方法的Java 8調用不明確

public static <T> ImmutableSet<T> append(Set<T> set, T elem) { 
    return ImmutableSet.<T>builder().addAll(set).add(elem).build(); 
} 

public static <T> ImmutableSet<T> append(Set<T> set, Set<T> elemSet) { 
    ImmutableSet.Builder<T> newSet = ImmutableSet.builder(); 
    return newSet.addAll(set).addAll(elemSet).build(); 

編譯器返回不明的匹配誤差方法在下面的測試追加

@Test(expected = NullPointerException.class) 
public void shouldAppendThrowNullPointerForNullSecondSet() { 
    ImmutableSet<Integer> obj = null; 
    CollectionUtils.append(ImmutableSet.of(1), obj); 
} 

編譯器錯誤:

reference to append is ambiguous both method append(java.util.Set,T) in CollectionUtils and method append(java.util.Set,java.util.Set) in CollectionUtils match

如何重寫這些函數與從Java8引入的類型推斷一起工作?

+1

你可以通過讓'ImmutableSet obj = null; \t \t ImmutableSet set = ImmutableSet.of(1); \t append(set,obj);'。 – Tunaki

+0

無法在ideone中重現(使用HashSet而不是ImmutableSet,但從類型推斷的角度來看這應該不重要)http://ideone.com/oT6SbF。 –

+0

@AndyTurner無法使用jdk 1.8.0_51(和Eclipse Mars.2)進行編譯。 – Tunaki

回答

7

您已經在Java 8中找到了新的通用目標類型推斷改進。其中有幾個堆棧溢出問題。 Such as this one

Java 8可以基於它作爲參數傳遞給它的方法來推斷泛型的返回類型。因此,當您撥打CollectionUtils.append(ImmutableSet.of(1), obj)時,Java 8會嘗試從與您的append方法之一匹配的靜態of調用中返回一個不可變集合。在這種情況下,它可以考慮返回一個ImmutableSet<Object>而不是你明確想要返回的ImmutableSet<Integer>。然後目前還不清楚您是否撥打append(Set<Object>, Object)append(Set<Integer>, Set<Integer>)

最簡單的解決方案是重命名第二個方法appendAll。或者,你可以遵循建議的修復here和您的電話更改爲類似:

CollectionUtils.append(ImmutableSet.<ImmutableSet<Integer>>of(1), obj); 

我會用重命名,雖然第二種方法自己堅持。當他們嘗試使用圖書館時,它會爲其他開發者節省相同的痛苦。