Java通配符具有 super 意外的行为

标签 java wildcard super

我编写了一个 Fruit 类,它实现了 Comparable 接口(interface)和 2 个子类:Apple 和 Orange。 我编写了一个方法,它返回 2 个水果之间的最大值(无论它意味着什么)。

请注意,我没有在 super 中使用任何通配符。

我认为 max 方法会失败,因为 Comparable 接口(interface)不是由 Apple 或 Orange 直接实现的。

问题: 为什么建议使用这种形式的通配符:

<T extends Comparable<? super T>>

如果没有 super 也能工作吗?

这是代码:

package main;

//Note that I did not use the super wildcard: <T extends Comparable<? super T>>
class Max {

  public static <T extends Comparable<T>> T getMax(T x, T y) {
    return x.compareTo(y) >= 0 ? x : y;
  }
}

class Fruit implements Comparable<Fruit> {
    public String name;

    public Fruit(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Fruit other) {
        return name.compareTo(other.name) == 0 ? 0 :
               name.compareTo(other.name) > 0 ? 1 : -1;
    }

}

class Apple extends Fruit {
    String name;

    public Apple(String name) {
        super(name);
    }

}

class Orange extends Fruit {
    String name;

    public Orange(String name) {
        super(name);
    }

}

public class Main {

    public static void main(String[] args) {

        Apple a = new Apple("apple");
        Orange o = new Orange("orange");
        Fruit f = Max.getMax(a, o); //It should not be allowed because T does not implement Comparable directly
        System.out.println(f.name);

  }
}

最佳答案

就您而言,T可以选择为Fruit ,以及声明 Fruit f = Max.getMax(a, o);会正确进行类型检查。因此,它有效。

Max.getMax()具有参数类型 T ,以及 T 子类型的实例也是 T 的实例,因此该方法接受 T 的任何子类型作为参数。

但是请注意,您的方法仍然存在 T 的问题只能推断为Fruit ,而不是Apple ,因此您无法返回 Apple :

Apple a = Max.getMax(apple1, apple2);

但是,请考虑 T是泛型类型参数:

public static <T extends Comparable<T>> T getMax(List<T> xs) {
  //...
}

泛型不是协变的,所以这个方法只能接受List<Fruit> ,但不是List<Apple>List<Orange> ,尽管 Apple s 可以与 Apple 进行比较等

如果将其更改为:

public static <T extends Comparable<? super T>> T getMax(List<T> xs) {
  //...
}

那么它就可以工作 List<Apple>List<Orange> .

关于Java通配符具有 super 意外的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24629547/

相关文章:

python - 什么是 python 中的 super (类型)?

java - 如何了解用户在 Spring security 中拥有的所有角色

java - 是否可以将传递给方法的参数限制为常量?

java - 为 LDAP 用户设置已经散列的密码(使用 Java)

ssl - 如何为 IIS 6 创建自签名通配符 SSL 证书?

python - 如何从派生类打印变量?

java - 如何在 Richfaces panelBar Item 中设置焦点?

java - 为我揭开通配符的神秘面纱

sql - 我可以在 "IN"MySQL 语句中使用通配符吗?

java - 编译成功但运行时出现错误