Home > Mobile >  Can't pass wildcard Comparator to function
Can't pass wildcard Comparator to function

Time:02-27

I have the following sort method in a clone of ArrayList:

@SuppressWarnings({"rawtypes", "unchecked"})
public void sort(Comparator<? super E> c){
    if(c == null){
        // Use ascending order (only works if types are comparable)
        class ascComparator<T> implements Comparator<T> {
            public int compare(T a, T b) {
                // This will raise an exception if the types are not comparable
                return ((Comparable)a).compareTo(b);
            }
        }
        c = new ascComparator<E>();
    }
    // Cast the internal array to comparable then call merge sort
    sorter.mergeSort((Comparable[])array, c);
}

The sorter object is an instance of Sort:

public class Sort {
    @SuppressWarnings("unchecked")
    public <E extends Comparable<E>> E[] mergeSort(E[] list, Comparator<? super E> c){
        ...
    }
}

I get the following error on the sorter.mergeSort line:

The method mergeSort(E[], Comparator<? super E>) in the type Sort is not applicable for the arguments (Comparable[], Comparator<capture#8-of ? super E>)

I'm not sure why this is happening as both the parameter and argument have type Comparator<? super E>.

CodePudding user response:

Problem comes due to the ? inside the <? super E> - two different ? could be different types and are handled like that. You can see that from the message part "capture#8-of ?".

Also your mixing of raw types and unchecked casts will not help to solve your problem. In your code you have to casts to Comparable without the type parameter.

CodePudding user response:

Thanks to everyone for their comments. I've now fixed it.

@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c){
    if(c == null){
        // Use ascending order (only works if types are comparable)
        class ascComparator<T> implements Comparator<T> {
            public int compare(T a, T b) {
                // This will raise an exception if the types are not comparable
                return ((Comparable<T>)a).compareTo(b);
            }
        }
        c = new ascComparator<E>();
    }
    // Cast the internal array to E then call merge sort
    sorter.sort((E[]) array, c);
}

As Kayaman said, I shouldn't use rawtypes so I've given ascComparator parameter T. I've also casted array to E instead of Comparable as it didn't do what I thought it did. I've also changed Sort:

@SuppressWarnings("unchecked")
private <E> E[] mergeSort(E[] list, Comparator<E> c){
    ...
}

As pointed out by Louis Wasserman I don't need the Comparable type cast.

  • Related