相同点:
-
抽象类和接口都是为了将方法进行抽象,然后让子类去实现,所以两者都可以定义抽象方法
-
这种父类是没有必要创建实例对象的,所以第二个相同点是它们都不能创建本类对象,只能由子类去实例化子类对象
不同点:
-
抽象类是对整个事物的抽象,包括属性和行为;接口是对事物的某一个行为进行抽象;抽象类是 is a 的关系,接口是 has a 的关系
-
子类要扩展它们时,对抽象类用的是extends关键字,称之为继承;接口用的是implements关键字,称之为实现
-
抽象类可以实现接口;接口只能继承接口,不能继承类;一个类最多只能继承一个父类,但可以实现多个接口;所以,当既可以用抽象类,又可以用接口时,尽量选择接口,这样,子类的灵活度更高
-
抽象类进一步抽象后,就诞生了接口,接口比抽象类更纯粹,因为接口没有了成员属性,只有方法
- 所以,子类实现接口后,唯一能做的就是重写方法
- 子类继承抽象类之后,连带着将父类的成员属性也继承过来了
-
抽象类可以定义成员属性;而接口不能定义成员属性,只能定义静态属性,而且只能用final关键字定义静态常量,不能定义静态变量
-
接口除了没有成员属性外,还没有构造器,可以说非常纯粹了。接口就是一个只有方法和静态常量的类
-
抽象类不能被实例化,要构造器有啥用呢?
- 它的作用就是限定子类的构造行为。比如,抽象类可以将构造器定义好几个参数,子类要想实例化则必须想办法传入这几个参数才行
一些版本差异:
-
在Java8之前,接口更加纯粹,那时接口只能定义抽象方法,不能实现方法,也不能定义静态方法。
-
到了Java8才可以定义静态方法,以及可以用default关键字来实现方法。
-
为什么在Java8增加了这个特性呢?
- 因为Java8许多原有的接口新增了很多方法,这些新增的方法会影响到之前的子类,如果子类中没有去实现新增的方法,子类就会编译失败。
- 为了保证向下兼容,Java8就推出了default关键字,被default关键字修饰的方法就不是抽象方法了,也就不会要求已有的子类去实现方法
-
default方法出现以后,大家发现很好用,就大量在接口中去实现一些默认逻辑
-
可是一个方法中实现复杂逻辑,就会导致代码难以维护,于是Java9推出了一个新特性,那就是能在接口中定义private方法,这样就可以将一些内部逻辑拆开了。
-
可以发现,越到后面,抽象类和接口的差异就越小,那什么时候该用抽象类,什么时候该用方法呢?
- 当需要让子类继承成员变量或者需要控制子类的实例化时,就用抽象类;否则用接口