Java 8对泛型方法的调用是模糊的

Xte*_*ter 7 java java-8

我正在将Java7代码移植到Java8,我想出了以下问题.在我的代码库中,我有两种方法:

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();
Run Code Online (Sandbox Code Playgroud)

编译器在以下测试中返回有关方法附加的模糊匹配的错误:

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

编译错误:

对append的引用是不明确的,CollectionUtils中的方法append(java.util.Set,T)和CollectionUtils中的方法append(java.util.Set,java.util.Set)匹配

如何重写这些函数以使用Java8引入的类型推断?

And*_*dyN 7

您已经在Java 8中找到了新的通用目标类型推理改进.它上面有一些堆栈溢出问题. 比如这个.

Java 8可以根据它作为参数传递给的方法推断泛型的返回类型.因此,当您调用时CollectionUtils.append(ImmutableSet.of(1), obj),Java 8会尝试从of与您的某个append方法匹配的静态调用返回不可变集.在这种情况下,它可以考虑返回a ImmutableSet<Object>而不是ImmutableSet<Integer>你明显想要返回的那个.然后不清楚你是否正在打电话append(Set<Object>, Object),或者append(Set<Integer>, Set<Integer>).

最简单的解决方案是重命名第二种方法appendAll.或者,你可以遵循建议的修复这里和您的电话更改为类似:

CollectionUtils.append(ImmutableSet.<ImmutableSet<Integer>>of(1), obj);
Run Code Online (Sandbox Code Playgroud)

我坚持自己重命名第二种方法.当他们尝试使用该库时,它将为其他开发人员带来同样的悲痛.