简体   繁体   中英

Incompatible Type error on same type when using Comparator

I have a generic class called Interval

package com.test;

//import statements

public class Interval<T extends Comparable<? super T>> {

    private boolean isStartInclusive;
    private T start;
    private T end;
    private boolean isEndInclusive;

    //Constructors

    //Getter and Setters

    //ToString

    //Hashcode and Equals

    //A public static method that returns comparator for use by other classes
    public static <T extends Comparable<? super T>> Comparator<Interval<T>> getIntervalComparator() {
        return (o1, o2) -> {
            //comparing logic that returns -1 or 1 or 0
        };
    }

}

Whenever I use this Comparator to sort a List<Interval<T>> it works.

List<Interval<T>> intervalsList1 = getIntervalsList();
intervalsList1.sort(Interval.getIntervalComparator());

But when I do this

List<Interval<T>> intervalsList1 = getIntervalsList1();
List<Interval<T>> intervalsList2 = getIntervalsList2();

Interval<T> interval1 = intervalsList1.get(i);
Interval<T> interval2 = intervalsList2.get(i);

int compareOneVsTwo = Interval.getIntervalComparator().compare(interval1, interval2); //line 85

I get an error saying

Error:(85, 76) java: incompatible types: com.test.Interval<T> cannot be converted to com.test.Interval<T>

Even when I do this

Interval<Integer> integerInterval1 = new Interval<>(true, 1, 2, true);
Interval<Integer> integerInterval2 = new Interval<>(true, 4, 5, true);
int compareOneVsTwo = Interval.getIntervalComparator().compare(integerInterval1, integerInterval2); //line 115

I get this error:

Error:(115, 72) java: incompatible types: com.test.Interval<java.lang.Integer> cannot be converted to com.test.Interval<T>

I do not understand what is causing this compilation error. The comparator inside the Interval class is not the natural sort order, but the order in which multiple classes use when they sort for their own purpose.

It should work if you separate the statement into two separate statements:

Comparator<Interval<T>> compareOneVsTwo = Interval.getIntervalComparator();
compareOneVsTwo.compare(interval1, interval2);

// or in the integer case:
Comparator<Interval<Integer>> compareOneVsTwo = Interval.getIntervalComparator();
compareOneVsTwo.compare(interval1, interval2);

(assuming T is an existing type)

This is because when they are the same statement, the compiler is not smart enough to know that you need a Comparator<Interval<Integer>> . You could need a Comparator<Interval<String>> or a Comparator<Interval<LocalDate>> , as far as the compile is concerned, because it doesn't look at the .compare call when inferring the type parameters for the getIntervalComparator call.

What happens when the compiler doesn't know? It uses the type bound on the type parameter, ie Comparable<? super T> Comparable<? super T> , so it thinks you need a Comparator<Interval<T>> , but T doesn't actually exist...

Another way to fix this is:

Interval.<Integer>getIntervalComparator().compare(...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM