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

时间:2016-03-15 10:13:28

标签: 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();

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

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

编译错误:

  

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

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

1 个答案:

答案 0 :(得分:7)

您已经在Java 8中找到了新的广义目标类型推断改进。它上面有一些堆栈溢出问题。 Such as this one

Java 8可以根据传递给参数的方法推断泛型的返回类型。因此,当您调用CollectionUtils.append(ImmutableSet.of(1), obj)时,Java 8会尝试从与您的of方法之一匹配的静态append调用返回不可变集。在这种情况下,它可以考虑返回ImmutableSet<Object>而不是您明确要返回的ImmutableSet<Integer>。然后不清楚您是在呼叫append(Set<Object>, Object)还是append(Set<Integer>, Set<Integer>)

最简单的解决方案是重命名第二种方法appendAll。或者,您可以按照建议的修正here进行操作,并将您的通话更改为:

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

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