Java 实现接口如何提供附加功能?

Java 实现接口如何提供附加功能?,java,Java,我理解接口是类的契约,如果类实现了接口,那么接口中的所有方法都必须在类中 下面是一个涉及此接口的示例,让我感到困惑: public class Contact implements Comparable<Contact> { private String name; public int compareTo(Contact other) { return name.compareTo(other.name); } } 但如果合同未执行类似

我理解接口是类的契约,如果类实现了接口,那么接口中的所有方法都必须在类中

下面是一个涉及此接口的示例,让我感到困惑:

public class Contact implements Comparable<Contact> {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}
但如果
合同
未执行类似的
可比

public class Contact {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}
调用
Collections.sort
将产生编译时错误,即使
compareTo
方法仍然存在


显然,通过实现接口可以提供额外的功能。除了强制结构之外,接口的用途是什么?

因为如果
联系人实现了可比较的
,那么
联系人
就是可比较的

让我们看一看源代码,在
ComparableTimSort.countRunAndMakeAscending()中有一行:

if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0)
如果没有,那么我显然无法将实例分配给
可比较的
类型,因此我不知道
Contact
有什么方法(不诉诸反射)

通过实现
Comparable
,我告诉编译器这个类是
Comparable
,因此可以在需要时作为一个类来处理。必须实施这些方法只是其中的一个副作用

至于为什么它是编译时而不是运行时错误,您只需要查看方法集合的声明。排序
即可找到:

public static <T extends Comparable<? super T>> void sort(List<T> list)

publicstatic上面的答案是技术上的,但是从设计的角度来看,它们在程序层之间创建了一个抽象层。在设计复杂系统时,这一点很重要,因为它减少了类之间的依赖性,并允许更高的可维护性

其他答案给出了更常见的接口用法。我还有两个想法:

  • 简单标记
    Serializable
    既不包含方法,也不包含常量,只需声明类的实例可以成功序列化为流并反序列化回来
  • JDK代理。
    代理
    只能代理接口。因此,要代理一个类,必须首先将其公共方法导出到一个或多个接口。它通常用于Spring框架AOP

不,“强制结构”完全是接口的目的。(虽然在Java8中有一些变化…)接口是优秀的、非常灵活的设计工具。是关于打字的。Collections.sort的声明类似于sort(Collection@krems
排序(Collection@BorisSpider我没有说完全是那样的,只是想让内容更容易理解。顺便说一句,sort函数不能将集合作为参数,因为不是每个集合都是有序的,事实上是集合。sort接受列表,实际签名在下面的答案中给出,如下所示:
它不是
@Se可序列化的
,因为这将是一个注释。事实上,
可序列化的
的使用是JDK中最糟糕的设计决策之一,不应该作为初学者的示例。标记接口不应该作为注释使用。第二个示例是对非常复杂的运行时的大规模过度简化过程。@BoristheSpider:感谢您注意到无关的
@
。我同意这是一个糟糕的设计,但它在JDK中,我花了相当长的时间才理解接口可以用作简单的标记(我自学了Java…).我也承认代理比我写的要复杂得多。我只想坚持使用Spring AOP需要使用接口的层分离这一事实。但你的答案比我的好得多:-)
final Comparable<Contact> contact = new Contact();
public static <T extends Comparable<? super T>> void sort(List<T> list)