为什么我们不能使用两个参数捕获方法的通配符?

时间:2015-06-08 07:28:20

标签: java generics wildcard

that问题相关。

我知道通配符捕获。例如,以下内容可用于撤消列表:

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));
    }
}

现在我试图为这种情况写同样的事情:

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);
}

我预计它也被编译好了。是否有可能为具有两个或更多参数的方法捕获wildacrds?

2 个答案:

答案 0 :(得分:4)

因为正如我在回答你的另一个问题时所说,编译器无法知道两个?代表相同的类型。

两个?代表某种未知类型。对于相同类型compareComparable方法需要两个T个对象。如果您从compare方法调用comp,则编译器无法确定两个?代表相同的类型。

答案 1 :(得分:2)

在这个方法中

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

两个参数共享相同的类型参数。

同时,对于另一种方法,情况并非如此:

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

在这里,编译器没有证据表明upperlower的类型参数是相同的,这就是为什么拒绝为编译提供绿灯的原因。

如果您希望两种方法共享相同的类型参数,则可以使类型参数类范围。例如:

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); 
     }
}

另一个选项(如果你不喜欢第一个选项)将为comp()compare()的类型参数引入一个相同的上限。例如:

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); 
}

此外,如果您想避免使用comp()方法进行投射,您可以执行以下操作:

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); 
     }
}