02-面向对象编程进阶-2
1. 多态
1.1. 是什么
多态是一种现象。
父类引用子类对象,且调用被子类对象重写过的方法,表现为对象的多态。
接口引用实现类对象,且调用被实现类对象实现的方法,表现为行为的多态。
成员变量不谈多态。
1.2. 优点
多态的情况下,扩展性更好了。
- 右边的对象是解耦合的,可以替换为左边的任意子类对象或实现。
- 定义方法的时候,形参用父类或接口,方法调用的时候,实参可以是,任意子类对象或实现。
1.3. 缺点
多态的情况下,不能使用子类对象或接口实现类的独有的方法。
解决方案:
强制类型转化,把父类引用,先用 instanceof 判断真实的类型,再转化。
Warn
存在继承/实现,就可以用强制类型转化,在编译阶段不会报错。
但是,在运行阶段可能报错类型转化异常 (ClassCastException)
因此,建议先用关键字 instanceof 判断真是类型,然后再强转。
补充:
- 编译看左边,运行看右边。
Animal a = new Dog() a.name //是Animal的值 a.cry是dog的cry方法
2. final
final 表示最终的、不可变的。能修饰类、方法、变量。
- final 类不能被继承
- final 方法不能被重写
- final 变量不能被改变,且只能赋一次值
- 基本类型变量存的是数据值本身
- 引用类型变量存的是引用的对象的地址值,引用的对象随然不能变,但是对象里的数据可以改变
3. 常量
被 final static 修饰的变量,叫常量。常量必须要初始化。
(可以在定义的时候赋值,也可以在静态代码块种初始化)
常量起名建议大写单词,多个单词下划线连接。
常量通常用于保存系统配置,便于维护。
编译期常量代替机制
如果常量是基本类型或字符串。编译期就确认了值(Java 编译器会把使用这个常量的地方替换成值到字节码中)
4. 抽象类、抽象方法
关键字 abstract,表示抽象,可以修饰类、成员方法
- 被 abstarct 修饰的类,叫抽象类。
- 抽象类最主要的特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现
- 抽象类中可以没有抽象方法,有抽象方法的类一定是抽象类
- 类该有的成员(成员变量、方法、构造器)抽象类都可以有
- 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
- 被 abstract 修饰的成员方法,叫抽象方法
- 只能由方法签名,不能有方法体
语法
...
4.1. 使用场景和作用
子类都需要做某个行为,但是具体做法不一样,可以把这个行为,设计成父类的抽象方法。
这样做,为了用的多态。
例如:动物叫,狗叫汪汪,猫叫喵喵。
4.2. 模板方法
方法中存在重复代码,使用模板方法,抽取重复代码,提供代码复用性,简洁性。
具体做法:
- 定义一个抽象类
- 定义一个模板方法,存放相同的代码,建议用 final 修饰(不能被子类重写)
- 定义一个抽象方法,让子类去重写有差异的代码。
5. 接口
5.1. 概述
联想到了枚举
接口是interface 修饰的一个结构,JDK 8 之前,接口里只能由成员变量(常量)、成员方法(抽象方法)
注意点:
- 接口是为了弥补单继承的缺点
- 和抽象类一样,不能用接口创建对象。接口是用来被其他类实现的。
- 一个类可以实现多接口
- 类实现接口,必须重写接口的所有抽象方法,否则,这个类要定义成抽象类。
语法
// 接口定义
修饰符 interface 名字 {
//成员变量 默认会加上的可省不写 public final static
//成员方法 默认会加上的可省不写 public abstract
}
//实现
修饰符 返回值类型 类 implements 接口名1,接口名2 {
}
5.2. 好处
- 弥补类单继承的不足,一个类可同时实现多接口
- 面向接口编程,不用关注具体实现,同时可以轻松切换实现(有利于程序解耦合)。web 开发中,service 就是例子。
5.3. 接口的多继承
语法
public interface C extends B , A{
//便于实现类去实现
}
5.4. jdk 8 开始新增的三个方法
增强接口的能力,便于项目的扩展和维护
接口中有方法体的方法,修饰符是:
- static 静态方法(类方法),只能用
接口名.方法名调用。默认会加上 public 修饰符 - default 默认方法(实例方法),只能用接口的
实现类对象调用。默认会加上 public 修饰符- default 修饰方法,只能在接口中使用,也叫做扩展方法。
- private JDK 9 开始支持,只能在接口内部调用(被 default 方法或 private 方法调用)

5.5. 其他
- 多个接口的签名冲突
- 接口不能多继承
- 类不能多接口实现
- 有同名默认方法
- 多接口中存在的情况,实现类重写这个方法,不会出现冲突
- 抽象类和接口中存在的情况,实现类还调用父类的。
补充
| 场景 | 调用行为 |
|---|---|
| 类和接口有同名方法 | 优先使用 类中的方法 |
| 需要调用接口默认方法 | 使用 接口名.super.方法名() |
Java 提供了一种显式调用接口默认方法的方式,用于解决多继承冲突,语法格式:
接口名.super.方法名 ()