11. 抽象类和接口
抽象类
在 Java 中,抽象类是一种特殊的类,它不能被直接实例化,只能被其他类继承。抽象类通常用于定义一些抽象的方法和属性,这些方法和属性可能在子类中有不同的实现。
抽象类的主要目的是提供一个公共的接口,让子类可以根据自己的需求进行扩展和实现。抽象类中的抽象方法没有具体的实现,只包含方法的签名,子类就知道它必须要实现该方法,而不可能忽略,若忽略 Java 编译器会提示错误。
抽象类声明和实现
在 Java 中抽象类和抽象方法的修饰符是 abstract
,注意抽象方法中只有方法的声明,没有方法的实现。
- 抽象类不能被实例化,只有具体类才能被实例化;
- 抽象类可以拥有默认的构造函数, 供子类实例化调用, 用于完成子类构建对象的一些公共任务;
- 抽象类中可以包含具体方法和抽象方法;
- 非抽象类(具体类) 若继承抽象类必须重写所有抽象方法。
1 | public abstract class 类名称 { |
普通类加上 abstract 关键字就变成了抽象类。一但类中包含有抽象方法的类必须定义为抽象类或者接口,否则编译时会提示 The type XXX must be an abstract class to define abstract methods
接口
比抽象类更加抽象的是接口,在接口中所有的方法都会被 public 和 abstract 修饰。
- Java 中不支持多继承,而是通过接口实现比多重继承更强的功能,java 通过接口可以使出于不同层次,甚至不相关的类具有相同的行为。
- 接口可以认为是特殊的抽象类,不能用于直接创建对象。接口的作用在于规定一些功能框架,具体功能的实现则通过该接口约束的类完成。
接口的定义:一般由常量和抽象方法组成
1 | [public] interface 接口名 [extends 父接口名列表 ] { |
- 声明接口可给出访问控制符
- 接口的继承同样使用 extends 关键字,多个父接口之间以逗号分隔
- 系统默认接口中所有属性的修饰都是 public static final 即全局常量
- 系统默认接口中所有方法的修饰都是 public abstract 即抽象方法
- 与类一样,接口也可以使用 instanceof 关键字,用来判断一个对象是否实现了某接口
接口的实现
- 定义了一套行为规范,一个类实现这个接口就是要遵守接口的定义规范,要实现接口中定义的所有方法.
- 一个类可以实现多个接口。接口间用逗号分隔;
- 如果实现某接口的类不是抽象类,则在类的定义部分必须实现指定接口的所有抽象方法;否则编译时会指示该类只能为抽象类是不能创建对象的.
- 接口的抽象方法的访问限制符默认为 public
Java 8 新特性默认方法和静态方法
Java 8 在接口中提供了声明默认方法和静态方法的能力。接口示例代码如下:
1 | public interface IHello { |
注意:在 Java 8 中,静态方法和默认方法都必须是 public 的,Java 9 去除了这个限制,它们都可以是 private 的,引入 private 方法主要是为了方便多个静态或默认方法复用代码。
总结
抽象类和接口是配合而非替代关系,它们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。比如,在 Java 类库中,有:
- Collection 接口和对应的 AbstractCollection 抽象类。
- List 接口和对应的 AbstractList 抽象类。
- Map 接口和对应的 AbstractMap 抽象类。
问一问
问: 抽象关键字 abstract 不可以和哪些关键字共存?
答: private
私有内容子类继承不到,所以,不能重写。但是,abstract 修饰的方法,要求被重写。两者冲突。
final
final 修饰的方法不能被重写。而 abstract 修饰的方法,要求被重写。两者冲突。
static
假如一个抽象方法能通过 static 修饰,那么这个方法,就可以直接通过类名调用。而抽象方法是没有方法体的,这样的调用无意义。所以不能用 static 修饰。
参考
- 丁振凡编著,《Java 语言程序设计(第2版)》华东交大版,2014.9
- Java 编程的逻辑-微信读书 https://weread.qq.com/web/reader/b51320f05e159eb51b29226kc81322c012c81e728d9d180