Java Comparator类型推断混淆

时间:2018-03-07 20:28:43

标签: java comparator

我对以下代码示例提出的问题很少。

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)可以使用T Pair<LocalDate, LocalDate>进行类型推断,themComparing也可以使用T作为Pair<LocalDate, LocalDate>进行类型推断。此外,如果我的想法是正确的,为什么Comparator<User> userNameComparator = Comparator.comparing(User::getName);可以编译而没有任何问题。我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:1)

Java类型提供者不能确定第一个.comparing将接受与第二个类型相同的类型,因此它猜测第一个方法的类型是{{1} },而Object没有实现Comparable。您可以通过指定方法的泛型类型来解决此问题:

Object, Pair<LocalDate, LocalDate>

答案 1 :(得分:0)

编译器无法在第一种情况下推断出Pair::getLeft的类型,但在第二种情况下可能是因为它使用变量的类型来推断类型,但是因为您立即致电thenComparing(),它无法访问此信息。

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

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