2016-03-15 67 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); 

我会用重命名,虽然第二种方法自己坚持。当他们尝试使用图书馆时,它会为其他开发者节省相同的痛苦。