有 Java 编程相关的问题?

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

java用泛型搜索数组中的最大元素

任务:

Write a generic method to find the maximal element in the range [begin, end) of a list.

答复:

public final class Algorithm {
    public static <T extends Object & Comparable<? super T>>
        T max(List<? extends T> list, int begin, int end) {

        T maxElem = list.get(begin);

        for (++begin; begin < end; ++begin)
            if (maxElem.compareTo(list.get(begin)) < 0)
                maxElem = list.get(begin);
        return maxElem;
    }
}

你能解释一下如何使用这个方法吗?以下签名的区别是什么:

public static <T extends Comparable<T>> 
    T max(List<? extends T> ar, int begin, int end) { ... }

共 (2) 个答案

  1. # 1 楼答案

    我想这里有两个问题:

    • 为什么需要边界Object
    • 为什么要使用Comparable<? super T>而不是Comparable<T>

    对于第一个问题,实际上并不需要给出显式的Object边界,但这可能取决于您希望删除方法的方式。使用显式Object绑定,您的类型参数将被擦除为Object,没有该绑定,它将被擦除为Comparable。大多数情况下,您不需要给出显式绑定,但这可能是API兼容性所必需的,如this post中所述

    至于第二个问题,如果您想将列表传递给List<T>,其中T是可比较的,那么使用Comparable<? super T>通常是一个好主意。为什么?假设您有一个类:

    class Employee implements Comparable<Employee> { }
    

    和一个子类:

    class PartTimeEmployee extends Employee { }
    

    你想把一个List<PartTimeEmployee>传递给一个List<T>。在你意识到你的PartTimeEmployee并没有真正实现一个Comparable<PartTimeEmployee>而是一个Comparable<Employee>之前,这看起来很简单,很简单。因此,您要做的是将T的边界更改为:

    T extends Comparable<? super T>
    

    。。然后你可以传递一个List<PartTimeEmployee>,因为它现在满足这个界限

    您必须这样做的原因是与,擦除(再次?)有关。对第一次看到这个错误时,您可能会从椅子上跳下来,并通过这样做快速使PartTimeEmployee具有可比性:

    class PartTimeEmployee extends Employee implements Comparable<PartTimeEmployee>
    

    。。。但是,嘿,你做错了。Java泛型不允许实现或扩展相同泛型类型的两个不同参数化实例化。您的意思是,PartTimeEmployee同时实现Comparable<Employee>Comparable<PartTimeEmployee>。这样,在PartTimeEmployee中就有两种方法:

    compareTo(PartTimeEmployee)
    compareTo(Employee)
    

    擦除后,它们都将成为:

    compareTo(Object)
    compareTo(Object)
    

    现在你有了重复的方法。这就是为什么它是非法的

    然而,在本例中,由于您有一个List<? extends T>作为参数类型,我认为您最好使用Comparable<T>,因为当您传递一个List<PartTimeEmployee>时,T将被推断为Employee,因此将满足边界

  2. # 2 楼答案

    问题public static <T extends Object & Comparable<? super T>>public static <T extends Comparable<T>>之间的区别

    第一部分:为什么

    正如在this answer中很好地解释的那样,这是为了与1.5API之前的API向后兼容。所以,如果你没有这个问题,你可以删除它

    第二部分:为什么{}而不是{}

    让我们看两个类AB,其中B继承A。您使这两个函数都实现了Comparable,但自然排序的逻辑在AB中是相同的。因此,您将编写类定义,如下所示:

    public class A implements Comparable<A> {}
    
    public class B extends A {}
    

    因此,B实现了Comparable<A>,而不是Comparable<B>。如果是后者,您将无法对List<A>进行排序,其中列表的元素都是BA类型。因此super

    来自JDK的示例:java.util.Datejava.sql.Date。后者继承前者。您将看到java.sql.Date实现了Comparable<**java.util.Date**>