java 是一门典型的面向对象的编程语言,包含非常多的基本机制在里面,之前遇到很多人问 java 中接口和抽象类的区别等等,所以自己也对这些进行了总结与记录。

接口/抽象类

  • 接口与抽象类是 java 中面向对象设计的两种基本机制

接口

  • 接口本质其实并不是一个类,接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到 API 定义和实现分离的目的。

  • 接口不能实例化;不能包含任何非常量成员,任何 field 都是隐含着 public static final 的意义;

  • 接口没有非静态方法实现,也就是说要么是抽象方法,要么是静态方法。 Java 标准类库中,定义了非常多的接口,比如 java.util.List

抽象类

  • 抽象类是不能实例化的类,用 abstract 关键字修饰 class ,其目的主要是代码重用。

  • 除了无法实例化外,形式上和普通的 Java 类并没有太大区别,抽象类中可以没有抽象方法也可以有多个抽象方法,也可以有普通方法

  • 抽象类主要抽取封装相关 Java 类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。 Java 标准库中,比如 collection 集合框架,很多通用部分就被抽取成为抽象类,例如 java.util.AbstractList

实现

  • Java 类实现 interface 使用 implements 关键词,继承 abstract class 则是使用 extends 关键词,我们可以参考 Java 标准库中的 ArrayList

    public class ArrayList<E> extends AbstractList<E> 
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
        //...
    }

扩展

  • Java 相比于其他面向对象语言,如 C++ ,设计上有一些基本区别,比如 Java 不支持多继承。这种限制,在规范了代码实现的同时,也产生了一些局限性,影响着程序设计结构。 Java 类可以实现多个接口,因为接口是抽象方法的集合,所以这是声明性的,但不能通过扩展多个抽象类来重用逻辑。

  • 在一些情况下存在特定场景,需要抽象出与具体实现、实例化无关的通用逻辑,或者纯调用关系的逻辑,但是使用传统的抽象类会陷入到单继承的窘境。以往常见的做法是,实现由静态方法组成的工具类( Utils ),比如 java.util.Collections 。设想,为接口添加任何抽象方法,相应的所有实现了这个接口的类,也必须实现新增方法,否则会出现编译错误。对于抽象类,如果我们添加非抽象方法,其子类只会享受到能力扩展,而不用担心编译出问题。

  • 接口的职责也不仅仅限于抽象方法的集合,其实有各种不同的实践。有一类没有任何方法的接口,通常叫作 Marker Interface ,顾名思义,它的目的就是为了声明某些东西,比如我们熟知的 Cloneable、Serializable 等。这种用法,也存在于业界其他的 Java 产品代码中。从表面看,这似乎和 Annotation 异曲同工,也确实如此,它的好处是简单直接。对于 Annotation ,因为可以指定参数和值,在表达能力上要更强大一些,所以更多人选择使用 Annotation

  • Java 8 增加了函数式编程的支持,所以又增加了一类定义,即所谓 functional interface ,简单说就是只有一个抽象方法的接口,通常建议使用 @FunctionalInterface Annotation 来标记。 Lambda 表达式本身可以看作是一类 functional interface ,某种程度上这和面向对象可以算是两码事。我们熟知的 RunnableCallable 之类,都是 functional interface ,这里不再多介绍了,有兴趣你可以参考: https://www.oreilly.com/learning/java-8-functional-interfaces 。还有一点可能让人感到意外,严格说, Java 8 以后,接口也是可以有方法实现的!

  • Java 8 开始, interface 增加了对 default method 的支持。 Java 9 以后,甚至可以定义 private default methodDefault method 提供了一种二进制兼容的扩展已有接口的办法。比如,我们熟知的 java.util.Collection ,它是 collection 体系的 root interface ,在 Java 8 中添加了一系列 default method ,主要是增加 LambdaStream 相关的功能。

  • 你可以参考下面代码片段:

public interface Collection<E> extends Iterable<E> { 

    /**  

    - Returns a sequential Stream with this collection as its source 
    - ...  

    **/
    default Stream<E> stream() {  
        return StreamSupport.stream(spliterator(), false);  
    }  

}

----------

微信公众号


欢迎关注公众号“云栖简码”