有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么用通配符创建的比较器的compare方法不能接受对象?

在Java中,创建比较器对象是合法的,如下所示:

Comparator<? super Number> comparator = new Comparator<Object>() {
    @Override
    public int compare(Object o1, Object o2) {
        // implementation here
    }
};

但您不能将此对象用于这样的简单调用:

Object o1 = new Object(), o2 = new Object();
comparator.compare(o1, o2);

为什么会这样?我认为? super Number意味着数字及其所有超类


共 (3) 个答案

  1. # 1 楼答案

    Comparator<? super Number> comparator意味着comparator指的是已知的能够接受Number(或者它是null)的东西

    AComparator<Object>可以接受ANumber;但是编译器不知道aComparator<? super Number>引用的值是aComparator<Object>还是aComparator<Number>。它所知道的是它是可以接受Number的东西,所以它只允许你通过

    Why so? I thought ? super Number means Number and all its superclasses.

    否:这意味着Number是可接受的类型,可以作为参数传递。换句话说,Number是可接受参数类型的子类型。换句话说,可接受的参数类型是Number的超类型,因此可以传递Number

    见:What is PECS (Producer Extends Consumer Super)?

  2. # 2 楼答案

    假设您使用了? super Double

    Comparator<? super Double> comparator = new Comparator<Object>() {
        // ...
    };
    

    您告诉编译器的是,您有一个比较器

    • 可能是aComparator<Double>,或者
    • 可能是aComparator<Number>,或者
    • 可能是aComparator<Object>,或者
    • 可能是aComparator<Serializable>

    即使您使用Comparator<Object>对其进行了初始化,编译器也不知道这一点,因为编译器不执行代码。编译器只知道变量包含上述类型之一的比较器

    由于变量可能包含一个比较器,该比较器的类型比Object更为特定,因此编译器不会认为传递Object是可以的

  3. # 3 楼答案

    o1o2不能用作参数的原因是,它们比Number更“通用”,因此它们可能指向一个类的实例,该类是从Number父链的某个点开始的不同层次结构的一部分。类似于,Son类直接位于Father的层次结构行中,但不在Grandfather类的SecondSon层次结构中。因此,无法传递对Grandfather类实例的引用,因为它可能指向其SecondSon层次结构中的实例

    我试图解释一个类似的观点