Java比较器类型推断混淆

3

以下代码示例有几个问题:

class HypotheticComparators {
    class Pair<U,T> {
        private U left;
        private T right;
        public U getLeft() {
            return left
        }
        public T getRight() {
            return right;
        }
    }

    class User {
        private String name;
        private Integer age;
        public String getName(){
            return name;
        }
        public Integer getAge() {
            return age;
        }
    }

    public static void main(String[] args){
        List<Pair<LocalDate,LocalDate>> dataIntevals = new ArrayList<>();

        //Doesn't Compile
        Comparator<Pair<LocalDate,LocalDate>> pairComparator1  = Comparator.comparing(Pair::getLeft).thenComparing(Pair::getRight);

        //This Compile
        Comparator<Pair<LocalDate,LocalDate>> leftComparator = Comparator.comparing(Pair::getLeft);
        Comparator<Pair<LocalDate,LocalDate>> pairComparator2 = leftComparator.thenComparing(Pair::getRight));

        //This compile
        Comparator<User> userComparator1 = Comparator.comparing(User::getName).thenComparing(User::getAge);

        //This also compile
        Comparator<User> userNameComparator = Comparator.comparing(User::getName);
        Comparator<User> userComparator2 = userNameComparator.thenComparing(User::getAge);

    }
}

对于这个语句,Comparator<Pair<LocalDate,LocalDate>> pairComparator1 = Comparator.comparing(Pair::getLeft).thenComparing(Pair::getRight);,我最初的想法是themComparaing无法从Comparator.comparing(Pair::getLeft)中推断出类型而无法编译。但我对这个想法并不满意,因为查看Comparator.comparingthenComparing的源代码,它们都被正确地泛型化了。
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor)
{
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

default <U extends Comparable<? super U>> Comparator<T> thenComparing(
        Function<? super T, ? extends U> keyExtractor)
{
    return thenComparing(comparing(keyExtractor));
}

Comparator.comparing(Pair::getLeft) 可以对类型为 Pair<LocalDate, LocalDate> 的 T 进行类型推断,thenComparing 也可以对类型为 Pair<LocalDate, LocalDate> 的 T 进行类型推断。此外,如果我的想法是正确的,为什么 Comparator<User> userNameComparator = Comparator.comparing(User::getName); 可以编译通过而没有任何问题。我是否漏掉了什么?

2个回答

2

Java类型推断器无法确定第一个.comparing将接受与第二个相同的类型,因此它猜测第一个方法的类型为Object,Pair<LocalDate,LocalDate>,而Object不实现Comparable。您可以通过为方法指定泛型类型来解决此问题:

Comparator<Pair<LocalDate,LocalDate>> pairComparator1  = Comparator
    .<Pair<LocalDate, LocalDate>, LocalDate>comparing(Pair::getLeft)
    .thenComparing(Pair::getRight);

0

编译器在第一种情况下无法推断Pair::getLeft类型的原因在于它使用变量类型来推断类型,但由于您立即调用了thenComparing(),它无法访问此信息。

您可以通过在新行上单独使用Comparator.comparing(Pair::getLeft);(而不将其保存到变量中)来检查此内容。编译器将无法推断类型。

这可以通过明确说明Pair<LocalDate,LocalDate>::getLeft来解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接