思维导图:
4.3 抽象类和接口的笔记
4.3.1 抽象类
-
定义:当一个类需要定义成员方法描述其行为特征,但这些方法的实现方式无法确定时,Java提供了抽象类来满足这种需求。
-
特点:
- 抽象方法是使用
abstract
关键字修饰的方法,无需实现方法体。 - 抽象类可以包含属性、普通方法和抽象方法。
- 抽象类中可以没有抽象方法,但包含抽象方法的类必须声明为抽象类。
- 抽象方法是使用
-
语法:
abstract class 抽象类名称 { 访问权限 返回值类型 方法名称(参数); 访问权限 abstract 返回值类型 抽象方法名称(参数); }
-
规则:
- 包含抽象方法的类必须是抽象类。
- 抽象类和抽象方法都使用
abstract
关键字修饰。 - 抽象方法只声明不实现。
- 非抽象子类必须重写抽象类中的所有抽象方法。
-
注意:
- 抽象方法不能被声明为
private
,因为它们必须在子类中被实现。
- 抽象方法不能被声明为
-
案例:文件4-10示例了一个
Animal
抽象类和其子类Dog
。Animal
类中有一个抽象方法shout()
,而Dog
类继承Animal
类并实现了shout()
方法。当创建Dog
对象并调用shout()
方法时,输出结果为“汪汪……”。
[4.3.2 接口] (根据您提供的信息,以下部分是基于可能的内容推断的。)
-
定义:接口是一种特殊的抽象类型,用于声明对象应该具备哪些方法。在Java中,接口主要用于声明方法规范。
-
特点:
- 接口中所有的方法默认都是公开且抽象的。
- 接口可以有默认方法和静态方法。
-
语法:
public interface 接口名称 { 返回值类型 方法名称(参数); }
-
注意:
- 接口中的方法默认访问权限是
public
,不允许使用其他访问修饰符。 - 接口不能直接实例化。
- 接口中的方法默认访问权限是
结论:抽象类和接口都提供了一种方式来定义对象应该如何表现,但它们的使用和目的略有不同。抽象类更多地关注于提供一个基础和部分实现,而接口更多地关注于提供规范和契
4.3.2 接口
接口是用于描述类或结构的一组相关行为的定义,没有实现。接口产生了“面向接口编程”的概念,即将程序的不同业务逻辑分离,并使用接口来连接不同的业务模块。接口中不实现任何业务逻辑,这些逻辑由实现接口的类来完成。当业务需求变更时,只需要更改实现类的逻辑而无需更改接口,从而降低了系统的维护成本。
类比实例:鼠标、U盘等外部设备通过USB接口连接到计算机上,非常方便。如果我们想更换外部设备,只需要更换USB设备即可,而不需要更改USB接口。这种思想就是面向接口编程。
在Java中,接口主要用于克服单一继承的局限性,因为一个类只能继承一个父类,但可以实现多个接口。在JDK 8之前,接口主要由全局常量和抽象方法组成。从JDK 8开始,接口可以定义默认方法和静态方法。
接口的定义:
[public] interface 接口名 [extends 接口1, 接口2, ...] {
[public][static][final] 数据类型 常量名 = 值;
[public][abstract] 返回值的数据类型 方法名(参数列表);
[public] static 返回值的数据类型 方法名(参数列表);
[public] default 返回值的数据类型 方法名(参数列表);
}
- 一个接口可以继承多个父接口。
- 接口中的变量默认为
public static final
(全局常量)。 - 接口中的抽象方法默认为
public abstract
。 - 接口不能直接实例化。
- 实现接口的类必须实现接口中的所有抽象方法。
- 一个类可以实现多个接口。
接口的实现:
修饰符 class 类名 implements 接口1, 接口2, ... {
// 实现接口中的方法...
}
示例:
interface Animal {
int ID = 1;
String NAME = "牧羊犬";
void shout();
public void info();
static int getID() {
return ID;
}
}
interface Action {
public void eat();
}
class Dog implements Animal, Action {
public void eat() {
System.out.println("喜欢吃骨头");
}
public void shout() {
System.out.println("汪汪……");
}
public void info() {
System.out.println("名称:" + NAME);
}
}
public class Example11 {
public static void main(String[] args) {
System.out.println("编号: " + Animal.getID());
Dog dog = new Dog();
dog.info();
dog.shout();
dog.eat();
}
}
如果一个类既要实现接口又要继承抽象类,可以使用以下语法:
修饰符 class 类名 extends 父类名 implements 接口1, 接口2, ... {
// 方法实现...
}
总结:
接口提供了一种方式来描述一个类应该做什么,而不是怎么做。这为代码的复用和模块化提供了方便。
Java接口和抽象类概述
1. Animal接口
- 位置:文件4-12中,第2~6行
- 内容:声明了全局常量
NAME
和抽象方法shout()
、info()
。
2. Action抽象类
- 位置:文件4-12中,第8~10行
- 内容:定义了抽象方法
eat()
。
3. Dog类(继承和实现)
- 位置:文件4-12中,第12~25行
- 内容:
- 继承了
Action
抽象类 - 实现了
Animal
接口 - 重写了
shout()
、info()
和eat()
方法。
- 继承了
4. 运行结果
- 文件:文件4-12
- 输出:
- 名称:牧羊犬
- 汪汪…
- 喜欢吃骨头
5. Color接口
- 位置:文件4-13中,第6~9行
- 内容:定义了抽象方法
black()
。
6. Action接口(接口的继承)
- 位置:文件4-13中,第11~13行
- 内容:
- 继承了
Animal
和Color
接口 - 定义了
shout()
方法。
- 继承了
7. Dog类(接口实现)
- 位置:文件4-13中,第15~28行
- 内容:
- 实现了
Action
接口 - 重写了
info()
、black()
和shout()
方法。
- 实现了
8. 运行结果
- 文件:文件4-13
- 输出:
- 名称:牧羊犬
- 汪汪…
- 黑色
综合点评:
Dog
类在文件4-12中实现了Animal
接口和继承了Action
抽象类,成功重写了相关方法并在测试类中进行了调用。- 在文件4-13中,接口的继承被展示,其中
Action
接口继承了Animal
和Color
接口。 Dog
类再次通过实现Action
接口,展示了如何重写多个继承自不同接口的方法。- 运行结果分别证明了
Dog
类成功地重写了不同来源的方法,并且可以通过实例化对象访问
总结:
抽象类
重点:
- 抽象类不能实例化,主要作为基类用于继承。
- 抽象类可以包含抽象方法(没有实体的方法)和具体方法。
- 子类继承抽象类必须实现其所有的抽象方法,除非子类也是抽象类。
难点:
- 理解抽象类与普通类的根本区别及其应用场景。
- 抽象类与普通类、接口之间的选择问题。
易错点:
- 尝试实例化一个抽象类。
- 忘记在继承抽象类的非抽象子类中实现所有抽象方法。
- 将不应该被实例化的类设计为普通类,而不是抽象类。
接口
重点:
- 接口是完全抽象的,不能包含具体的方法实现。
- 类可以实现多个接口,解决了Java单继承的局限。
- 接口中的变量默认为
public static final
,方法默认为public abstract
。
难点:
- 理解接口与抽象类的区别和各自的应用场景。
- 理解如何在实现多个接口时处理可能出现的名称冲突或相同方法签名。
易错点:
- 在接口中定义具体的方法实现(Java 8后,接口可以有默认方法和静态方法,但这是特例)。
- 将接口中的变量当作非
final
来使用,试图修改它们。 - 实现多个接口时,忘记实现其中某个接口的某个方法。
抽象类与接口的对比
难点:
- 何时使用抽象类,何时使用接口。
- 如何在类的设计和继承/实现关系中平衡抽象类和接口的使用。
易错点:
- 在需要多重继承功能的场景中选择抽象类而不是接口。
- 在设计时过于依赖抽象类,导致系统缺乏灵活性。
- 混淆抽象类和接口的语法,如尝试使接口继承类或使抽象类实现接口但不提供方法的实现。