键入变量,方法内联和“lambda表达式中的错误返回类型”

时间:2016-02-23 09:33:26

标签: java lambda java-8

我正在使用新的Java 8功能:接口中的lambda,default和static方法。

此代码可以正常工作:

@FunctionalInterface
interface Comparator<T> {
    int compare(T a, T b);

    static <T> Comparator<T> comparing(Function<T, Comparable> f) {
        return (a, b) -> f.apply(a).compareTo(f.apply(b));
    }

    default Comparator<T> thenComparing(Comparator<T> comp) {
        return (a, b) -> compare(a, b) == 0 ? comp.compare(a, b) : compare(a, b);
    }

    default Comparator<T> thenComparing(Function<T, Comparable> f) {
        return thenComparing(comparing(f));
    }
}

如果我将thenComparing(Comparator<T> comp)内联到thenComparing(Function<T, Comparable> f)

@FunctionalInterface
interface Comparator<T> {
    int compare(T a, T b);

    static <T> Comparator<T> comparing(Function<T, Comparable> f) {
        return (a, b) -> f.apply(a).compareTo(f.apply(b));
    }

    default Comparator<T> thenComparing(Function<T, Comparable> f) {
        return (a, b) -> compare(a, b) == 0 ? comparing(f) : compare(a, b);
    }
}

编译失败:

error: incompatible types: bad return type in lambda expression
  return (a, b) -> compare(a, b) == 0 ? comparing(f) : compare(a, b);
                                                       ^
bad type in conditional expression
  no instance(s) of type variable(s) T exist so that Comparator<T> conforms to int
where T is a type-variable:
  T extends Object declared in method <T>comparing(Function<T,Comparable>)

为什么?

另一个版本没有使用Comparable作为原始类型:

@FunctionalInterface
interface Comparator<T> {
    int compare(T a, T b);

    static <T, U extends Comparable<U>> Comparator<T> comparing(Function<T, U> f) {
        return (a, b) -> f.apply(a).compareTo(f.apply(b));
    }

    default Comparator<T> thenComparing(Comparator<T> comp) {
        return (a, b) -> compare(a, b) == 0 ? comp.compare(a, b) : compare(a, b);
    }

    default <V extends Comparable<V>> Comparator<T> thenComparing(Function<T, V> f) {
        return thenComparing(comparing(f));
    }
}

2 个答案:

答案 0 :(得分:5)

这不起作用,因为:

  • comparing(f)返回Comparator<T>
  • compare(a, b)会返回int

因此类型在三元表达式中不兼容:

(a, b) -> compare(a, b) == 0 ? comparing(f) : compare(a, b);
                               ^----------^   ^-----------^
                               Comparator<T>       int

你想要的是在比较比较器的下一个上调用.compare(a, b),如果第一个返回相同的项目:

default Comparator<T> thenComparing(Function<T, Comparable> f) {
    return (a, b) -> compare(a, b) == 0 ? comparing(f).compare(a, b) : compare(a, b);
}

作为旁注,您使用Comparable作为原始类型。 Don't do that

答案 1 :(得分:4)

内联

default Comparator<T> thenComparing(Comparator<T> comp) {
    return (a, b) -> compare(a, b) == 0 ? comp.compare(a, b) : compare(a, b);
}

进入

default Comparator<T> thenComparing(Function<T, Comparable> f) {
    return thenComparing(comparing(f));
}

导致

default Comparator<T> thenComparing(Function<T, Comparable> f) {
    return (a, b) -> compare(a, b) == 0 ? comparing(f).compare(a, b) : compare(a, b);
}

而不是

default Comparator<T> thenComparing(Function<T, Comparable> f) {
    return (a, b) -> compare(a, b) == 0 ? comparing(f) : compare(a, b);
}