简体   繁体   中英

Why can't we capture wildcards for the method with two parameters?

Related to that question.

I know about wildcard capturing. For instance, the following could be used for reversing a list:

public static void reverse(List<?> list) { rev(list); } //capturing the wildcard
private static <T> void rev(List<T> list) {
    List<T> tmp = new ArrayList<T>(list);
    for (int i = 0; i < list.size(); i++) {
        list.set(i, tmp.get(list.size()-i-1));
    }
}

Now I'm trying to write the same thing for that kind of situation:

private int compare (Comparable<?> upper, Comparable<?> lower){
    return comp(upper, lower);  //The method comp(Comparable<T>, Comparable<T>) is not applicable for the arguments (Comparable<capture#5-of ?>, Comparable<capture#6-of ?>)
}

private <T> int comp(Comparable<T> upper, Comparable<T> lower){
    return upper.compareTo((T) lower);
}

I expected that it was compiled fine as well. Is it possible to capture wildacrds for methods with two or more parameters that way?

Because, as I said in my answer to your other question, the compiler cannot know that the two ? stand for the same type.

The two ? each stand for some unknown type. The compare method needs two Comparable objects for the same type T . If you call compare from the comp method, the compiler cannot be sure that the two ? stand for the same type.

In this method

private <T> int comp(Comparable<T> upper, Comparable<T> lower){
    return upper.compareTo((T) lower);
}

both of the parameters share the same type-parameter.

Meanwhile, this is not true for the other method:

private int compare (Comparable<?> upper, Comparable<?> lower){
    return comp(upper, lower); 
}

Here, the compiler has no evidence that the type-parameters for upper and lower are the same and that's why refuses to give green light to compilation.

If you want both of the methods to share the same type-parameter(s), you can make the type-parameter class-scoped . For example:

public class YourClass<T> {
     private int comp(Comparable<T> upper, Comparable<T> lower){
         return upper.compareTo((T) lower);
     }

     private int compare (Comparable<T> upper, Comparable<T> lower){
         return comp(upper, lower); 
     }
}

Another option (if you don't like the first one) would be to introduce one and the same upper bound for the type-parameters for comp() and compare() . For example:

private <T extends SomeSuperClass> int comp(Comparable<T> upper, Comparable<T> lower){
    return upper.compareTo((T) lower);
}

private <T extends SomeSuperClass> int compare (Comparable<T> upper, Comparable<T> lower){
    return comp(upper, lower); 
}

Furthermore, if you want to avoid the casting in the comp() method, you can do:

public class YourClass<T extends SomeSuperClass & Comparable<T>> {
     private int comp(T upper, T lower){
         return upper.compareTo(lower);
     }

     private int compare (T upper, T lower){
         return comp(upper, lower); 
     }
}

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