经典回答
接口和抽象是Java 面向对象设计的两个基础机制。
接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到API 和实现分离的目的。它不包含任何非常量的变量,同时没有方法实现。JDK1.8 后引入的default 后可以。用关键字implements 实现。
抽象类是不能实例化的类,用关键字abstract 修饰,其主要目的是代码重用。除了不能实例化,形式上和一般的 Java 类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java 类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。
一个类可以单继承多实现。
以下为网上摘取的不同点:
考点分析
接口和抽象的区别是面试中经常问到的考点。虽然很简单,但是往深了想其实还是有很多值得我们在意的地方。主要是设计方面的问题。
考点一:Java 为什么是单继承多实现?
我们都知道C++ 可以实现多继承。但是多继承会出现菱形继承的问题:A 类实现了一个方法,B、C类分别继承与A 并重写了这个方法,D 类继承B、C 但是不知到该调用谁的方法。虽然C++ 提供了解决办法(好像是虚继承),但是还是不方便。Java 因此摒弃了多继承。
为什么可以多实现呢?首先接口不可能出现菱形继承关系:A 接口被B、C 类实现,D 因为单继承只能选择一个来进行继承。其次,就算实现的两个接口拥有相同的方法名,在实现里面也不会出现歧义。
无论是A 还是B 来回调函数,都可以找到实现。只是这样设计不太好。
考点二:接口和抽象都可以实现抽象方法,为什么还要设计两个?
这种问题其实在很多地方都可以问到,比如多线程既然Thread 可以直接start,何必要设计一个Runnable 接口,多此一举?
new Thread().start(); new Thread(new Runnable()).start; //伪代码
其实回答这些问题无非两个关注点:
- 功能
- 简洁
接口更关注在于API 和实现分离,而继承更关注与方法和属性重用;同时接口更简洁,抽象需要额外继承很多父类的东西。
考点三: 对JDK 新特性的掌握
JDK1.8 引入default 关键字让接口可以实现具体方法,之所以这样设计的原因是延展性考虑。类似于各种集合接口,它的实现类有很多,如果这种接口想要增加新方法,比如1.8 增加stream 流的操作,意味着所以实现类必须同样增加实现?哪也太不便于维护和更新了,估计Java 底层设计师看到这个需求可以直接申请辞职了。
拓展
对设计模式的理解
我们在设计抽象和接口的时候需要考虑设计模式,常用的设计模式也就是所谓的 S.O.L.I.D 原则。
这里后面会补充