接口

接口是不是类,是对类的一组需求的描述,这些类要遵从接口描述的同一格式进行定义(其是对行为的抽象,是抽象方法的集合)。有两个方面的职责:

  1. 抽象方法的集合(主要
  2. 声明某些东西(Mark Interface)

通过接口,可以达到API和实现的分离,譬如MVC中的dao层或service层,但是不能实例化,同时也不能包含任何非常量成员,所以,也隐含表明,任何的field都具有public static final的意义。同时对于方法来说,接口中要么是抽象方法,要么是静态方法。如Collection框架中root interface java.util.Collection

疑问1:为什么常量成员默认修饰为public static final

  1. 接口必须要具体类实现才有意义,所以必须是public。

  2. 接口中的属性对所有实现类只有一份,所以是static。

  3. 要使实现类为了向上转型成功,所以必须是final的。

疑问2:为什么方法要么是抽象方法,要么是静态方法

抽象方法和接口定义的方法,你可以理解为是一种协议或者规范。比如我们是行业的达人,需要定义车的规范,它能启动、跑起来、刹车和停止,这4项功能就是抽象方法。至于用什么引擎启动、跑地多快、怎么刹车,我们就不想管了,你爱怎么实现是你的事,但你必须实现我们定义好的抽象方法,否则你生产的就不是车子了。

以最常用的java.util.List为例,它的继承树及其庞大。但这些实现类和继承类,都有共同的方法,也就是List定义的方法,比如get/add/remove/size。这样就保证了后续子孙都是一个模样的,但有个性。

List list = new 实现类();
list.add(obj);list.get(0);int size = list.size();// 这行代码不需要修改
实现类可以是ArrayList,也可以是LinkedList,或者是线程安全的CopyOnWriteArrayList。爱换那个换那个,但第二行的代码不需要修改,因为它们都使用了List的规范。

1、接口是一种约束和规范,是一种更加更高级的抽象类,抽象类的方法必须是公开的,因为要给人继承和使用啊,不用public,别人怎么看得到,所以在接口实现时,定义的方法修饰符必须是public;因此子类在实现接口重写方法时的修饰符必须是public。
2、另外再扩展一下,接口中没有变量(既然是约束和规范,怎么能够定义一个大家都可以改的东西呢?),只能是常量,接口中定义常量默认的修饰符为public static final。

抽象类

类似于模板,但又不同,目的是提高代码的复用,其抽取了相关的Java类的共用方法,或共用的成员变量,通过继承的方法达到代码复用目的。譬如Collection框架中的各种AbstractXXX类。抽象类除了不能实例化,形式上和Java类没有太大区别。

总结

接口:

  1. 只有常量
  2. 方法要么是抽象方法、要么是静态方法
  3. 不能被实例化
  4. 一个类可以实现多个接口

抽象类:

  1. 除了不能实例化,其他和普通类没太大区别
  2. 一个类只能继承一个抽象类(Java 不支持多继承

核心区别

  1. 行为规范: 接口

  2. 通用功能: 抽象

在一些情况下存在特定场景,需要抽象出与具体实现、实例化无关的通用逻辑,或者纯调用关系的逻辑,这样的话,因为Java不支持多继承,就无法使用抽象类进行实现,常用的方法是实现由静态方法构成的工具类,比如java.util.Collections

接口的职责也不仅仅限于抽象方法的集合,其实有各种不同的实践。有一类没有任何方法的接口,通常叫作 Marker Interface,顾名思义,它的目的就是为了声明某些东西,比如我们熟知的 Cloneable、Serializable 等。这种用法,也存在于业界其他的 Java 产品代码中。

References

  • Java核心卷I