BCSP-玄子JAVA开发之面向对象编程CH04_ 抽象类和接口笔记
8.1 抽象类
[访问修饰符] abstract class <类名> {}
// 中括号包裹的表示可有可无
抽象类不能被实例化
8.1.1 抽象方法
[访问修饰符] abstract class 类名 {
[ 访问修饰符 ] abstract < 返回类型 > < 方法名 >([ 参数列表 ]);
// 只有方法声明,无具体实现
}
有抽象方法的类必然是抽象类,但抽象类中的方法并不一定都是抽象方法
抽象类中使用抽象方法优化代码
-
abstract
关键字也可用于方法——抽象方法 -
抽象方法没有方法体
-
抽象方法必须在抽象类里
-
抽象方法必须在子类中被实现,除非子类是抽象类
8.1.2 抽象类的优势
提高可重用性
- 抽象类可以看作是类的一个模版,定义了子类的行为,可以为子类提供默认实现,无需子类中重复实现这些方法
代码松耦合,更易于维护
- 子类可以分别实现抽象父类中定义的抽象方法,将方法定义和方法实现的分离
方便实现多态
- 抽象类作为继承关系下的抽象层,不能被实例化,通常定义抽象类类型变量,其具体引用是实现抽象类的子类对象
8.1.3 抽象类的应用场合
-
抽象类用来列举一个类所需要的共性行为
-
抽象类不明确提供具体实现方法
-
抽象类必须由其子类实现它的抽象方法(除非子类也具有抽象性)
-
父类提供一系列规定,约束子类的行为
-
抽象类和抽象方法实现多态性
8.1.4 抽象类与抽象方法
抽象方法只有方法声明,没有方法实现
-
有抽象方法的类必须声明为抽象类
-
子类必须重写所有的抽象方法才能实例化;否则,子类也必须声明成抽象类
-
抽象类中可以没有、有一个或多个抽象方法,甚至可以定义全部方法都是抽象方法
-
抽象类可以有构造方法,其构造方法可以被本类的其他构造方法调用,不是由 private 修饰构造方法,可以被其子类的构造方法调用
abstract 可以用来修饰类和方法,不能用来修饰属性和构造方法
8.2 Final 用法
- 使用 final 修饰的类不可被继承
public final class Dog extends Animal {
// 不能被继承
}
- 使用 final 修饰的方法不可被重写
public class Dog {
public final void eat() {
System.out.println("狗吃骨头");
// 不能被重写
}
}
- 使用 final 修饰的常量不可被修改
public class Dog {
final String name =“小狗";
public void setName(String name) {
this.name=name; //错误,不可再赋值
}
}
8.2.1 Final关键字的用法
-
final可以用来修饰类、方法和属性,不能修饰构造方法
-
Java提供的很多类都是final类,不能重写
- 如:String类、Math类
-
Object类有一些final方法,只能被子类继承而不能被重写
- 如:getClass( )、notify( )、wait( )
-
Object类的hashCode( )、toString( )、equals(Object obj)方法不是final方法,可以被重写
8.3 常见错误
8.3.1 错误一
public class Student {
String name;
public Student(String name) {
this.name = name;
}
public static void main(String[] args) {
final Student stu = new Student("李明");
stu.name = "李明航";
stu = new Student("王亮");
// 使用final修饰的引用型变量,不可以再指向其他对象
}
}
使用 final 修饰引用型变量,变量的值是固定不变的,而变量所指向的对象的属性值是可变的
8.3.2 错误二
class Value {
int v;
}
public class Test {
public void changeValue(final int i, final Value value) {
i = 8;
// 使用final修饰的方法参数,在整个方法中不能改变参数值
value.v = 8;
}
}
使用 final 修饰的方法参数,这些参数的值是固定不变的
8.3.3 错误三
public static abstract void print();
抽象方法只有声明无具体实现,static 方法可通过类名直接访问,但无法修饰一个没有实现的方法
private abstract void print();
抽象方法需在子类中重写,但 private 方法不能被子类继承,自然无法进行重写
public final abstract void print();
抽象方法需要在子类中重写,但 final 修饰的方法表示该方法不能被子类重写,前后是相互矛盾的
8.4 接口
8.4.1 什么是接口
生活中的接口就是一套规范
- 如:主板上的PCI插槽有统一的标准,规定了尺寸、排线
Java 中的接口
-
是一种规范和标准
- 可以约束类的行为,使得实现接口的类(或结构)在形式上保持一致
-
是一些方法特征的集合
-
可看作是一种特殊的
抽象类
-
但采用与抽象类完全不同的语法
-
抽象类利于代码复用,接口利于代码的扩展和维护
8.4.2 定义接口
接口是一个不能实例化的类型
[访问修饰符] interface 接口名 {
// 如果是 public,则在整个项目中可见如果省略,则只在该包中可见
// interface 定义接口的关键字
}
接口中的变量都是全局静态常量
-
自动使用public static final修饰
-
必须在定义时指定初始值
8.4.3 实现接口
类实现接口
class 类名 implements 接口名 {
// implements 实现接口使用的关键字
}
-
实现类必须实现接口的所有方法
-
实现类可以实现多个接口
JDK1.8 版本之前,接口中只能定义抽象方法,自 JDK1.8 版本开始,接口还允许定义静态方法和默认方法
向后兼容
- 允许开发者在已有接口里添加新的方法时不需改动已经实施该接口的所有实现类
8.4.4 定义复杂的接口
接口的多继承
[ 访问修饰符 ] interface 接口名 extends 父接口 1, 父接口 2,……{
// 通过extends实现接口的继承关系
// 多个父接口之间用“,”分隔
}
一个接口可以继承多个接口,但接口不能继承类
类实现多个接口
[ 访问修饰符 ] class 类名 extends 父类名 implements 接口 1, 接口 2,……{
// 通过implements实现多个接口
}
- 一个普通类只能继承一个父类,但能同时实现多个接口
extends
关键字必须位于implements
关键字之前- 类
必须实现
所有接口(接口1、接口2……)的全部抽象方法
,否则必须定义为抽象类
8.4.5 接口是一种能力
接口有比抽象类更好的特性
-
可以被多继承
-
设计和实现完全分离
-
更自然的使用多态
-
更容易搭建程序框架
-
更容易更换实现
8.5 面向对象设计原则
为了让代码更具灵活性,更能适应变化,需遵循的原则
-
摘取代码中变化的部分,形成接口
-
多用组合,少用继承
-
面向接口编程,不依赖于具体实现
-
针对扩展开放,针对改变关闭
- 开闭原则
面向接口编程可以实现接口和实现的分离,能够在客户端未知的情况下修改实现代码
BCSP-玄子JAVA开发之面向对象编程CH04_ 抽象类和接口笔记 2.4