Java 和可比

Java and Comparable

我是新来的,这是我的第一个 post。我刚刚完成了 Java OCA,现在开始攻读 OCP。我有一个关于 Comparable 接口的问题。

我有这个代码片段,它解释了 Comparable 是如何实现的:

import java.util.*;
public class Duck implements Comparable<Duck> {
private String name;
public Duck(String name) {
this.name = name;
}
public String toString() {   // use readable output
return name;
}
public int compareTo(Duck d) {
return name.compareTo(d.name); // call String's compareTo
}
public static void main(String[] args) {
List<Duck> ducks = new ArrayList<>();
ducks.add(new Duck("Quack"));
ducks.add(new Duck("Puddles"));
Collections.sort(ducks); // sort by name
System.out.println(ducks); // [Puddles, Quack]
}
}

我或多或少明白这里发生了什么,但在这段代码片段下面,作者引用了:

The Duck class implements the Comparable interface. Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object.

我的问题是为什么它没有可比性?这是否与以下事实有关:Collections.sort() 等调用代码会在内部使用 Comparable 类型作为参考参数来比较任何对象?

在此先感谢您的帮助,希望我的问题有道理。

My question is why would it not be comparable? Is this something to do with the fact that calling code such as the Collections.sort() would internally use the Comparable type as a reference parameter to compare any object?

我不确定参考参数的确切含义。

在Java中,class仅提供接口(或class)方法的实现是不够的成为那个类型。它必须在 class 声明中 明确地 提及。


Collection class.

上有两个重载的 sort 实用方法
public static <T extends Comparable<? super T>> void sort(List<T> list)

public static <T> void sort(List<T> list, Comparator<? super T> c)

当您的 class 实现 Comparable 时,您可以在第一个方法中只传递 class 的对象列表。如果它不实现 Comparable,它将不会编译,因为 T 的边界必须 扩展 Comparable。在这种情况下,您将被迫传递显式 Comparator 来比较对象。

正如本书作者所提到的,具有与任意接口(或 class)中的方法签名相同的方法并不能构成该类型。

Duck Typing 不适用于 Java

Java 是一种基于面向对象的语言。其中支持继承通过classes/多态通过class/abstractclass/interface

interface Comparable<T> {
  // methods
}

class Person implements Comparable<Person> {
//methods
}

这实质上意味着 Person 类型的任何对象也属于 Comparable 类型。

interface Runnable {}
class Task implements Runnable {}

这意味着任何由 Task class 创建的对象也是 Runnable 类型。

作者是这个意思

如果您没有实现 Comparable 接口,但定义了 compareTo() 方法,那么您只是在 class 中定义了一个方法,就像任何其他方法一样。 您没有覆盖定义的 Comparable 接口中的 compareTo() 方法。

您仍然可以使用 compareTo() 方法比较每个对象,但您需要定义自己的排序方法,该方法会在内部调用 compareTo() 方法以按排序方式获取列表。

Java API Collections.sort() 在内部将列表转换为 Object[] 并调用 Arrays.sort()。现在 Arrays.sort() 将使用 TimSort 算法的修改版本进行排序,合同是 - 只有当数组元素属于可比较类型时,它才会对数组元素进行排序。

  • ComparableTimSort
  • Collections.sort()

你可以查一下,对于所有的内部调用,上面写得很清楚:

@throws IllegalArgumentException (optional) if the comparator is found to violate the {@link Comparator} contract

因此,要将任何对象类型传递给 sort(),它也必须是 Comparable 类型。 Strings/Wrappers 已经是可比类型。因此,您需要在定义用户定义的对象时注意这个契约。

"Without implementing that interface, all we have is a method named compareTo(), but it wouldn't be a Comparable object."

-简单来说,就是不实现接口,你有一个Duck类型的对象,不是可比类型