完整教程:Java 抽象(abstract)关键字
1. 什么是 abstract 关键字?
abstract
是 Java 中一个非常重要的关键字,中文意思是"抽象的"。它就像一个“未完成的蓝图”或一个“概念模型”,用来定义一些必须存在但暂时无法确定具体实现的东西。
核心思想:
- 规定必须做什么(What),但不规定具体怎么做(How)。
- 用于强制子类遵循某种结构或实现特定行为。
- 提高代码的灵活性和可扩展性,是实现多态和框架设计的基础。
2. 如何理解抽象?一个生动的比喻
想象一下你要造车:
- 抽象类就像是一份《汽车设计规范》。
- 规范里规定:一辆车必须有方向盘、发动机、轮胎(这些就是抽象方法)。
- 但规范不会规定方向盘是圆的还是方的,发动机是燃油的还是电动的。
- 具体子类就像是根据这份规范造出的具体车型,比如“宝马燃油车”和“特斯拉电动车”。
- 它们都满足了规范的所有要求(都有方向盘、发动机、轮胎)。
- 但各自实现了发动机的具体工作方式(燃油驱动 vs 电力驱动)。
abstract
关键字就是用来编写这份《设计规范》的工具。
3. abstract 修饰类(抽象类)
当一个类被 abstract
修饰时,它就成为了一个抽象类。
3.1 语法与特点
// 使用 abstract 关键字声明一个抽象类
public abstract class Animal
{
// 抽象类可以包含普通字段
private String name;
// 抽象类可以包含普通方法(有具体实现)
public void eat() {
System.out.println("This animal is eating.");
}
// 抽象类可以包含抽象方法(没有方法体)
public abstract void makeSound();
}
3.2 抽象类的核心规则
- 不能实例化:你不能使用
new
关键字直接创建一个抽象类的对象。Animal myAnimal = new Animal(); // 编译错误!Animal是抽象的,无法实例化
- 必须被继承:抽象类生来就是被当爸爸的。必须有一个子类(可以是普通类,也可以是抽象类)来继承它。
- 可以包含混合成员:抽象类里既可以有普通方法(带实现的),也可以有抽象方法(不带实现的),还可以有构造方法、字段等。这是一个与接口的关键区别。
4. abstract 修饰方法(抽象方法)
当一个方法被 abstract
修饰时,它就成为了一个抽象方法。
4.1 语法与特点
public abstract void makeSound();
// 注意:没有方法体{},直接以分号;结束
- 没有方法体:抽象方法只有方法声明(方法名、参数、返回类型),没有大括号
{}
包裹的实现代码。 - 必须在抽象类中:一个类如果包含了抽象方法,那么这个类必须被声明为抽象类(
abstract class
)。 - 强制子类实现:任何继承了这个抽象类的普通子类,必须重写(Override)父类中的所有抽象方法,并提供具体的实现。如果不重写,那么这个子类自己也必须声明为
abstract
。
5. 代码示例:从抽象到具体
让我们用 Animal 的例子把抽象类和抽象方法串起来。
5.1 定义抽象类和方法
// 抽象类:Animal(动物)
public abstract class Animal
{
private String name;
// 构造方法
public Animal(String name) {
this.name = name;
}
// 普通方法
public void sleep() {
System.out.println(name + " is sleeping. Zzz...");
}
// 抽象方法:动物都会叫,但叫声不同,所以定义为抽象的
public abstract void makeSound();
}
5.2 创建具体子类实现抽象方法
// 具体子类:Dog(狗)
public class Dog
extends Animal {
// 继承抽象类Animal
// 调用父类的构造方法
public Dog(String name) {
super(name);
}
// 必须重写(实现)抽象方法 makeSound()
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
}
// 具体子类:Cat(猫)
public class Cat
extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void makeSound() {
// 实现了相同的抽象方法,但行为不同
System.out.println("Meow! Meow!");
}
}
5.3 使用这些类
public class Test
{
public static void main(String[] args) {
// Animal animal = new Animal("Generic Animal"); // 错误!不能实例化抽象类
Animal myDog = new Dog("Buddy");
// 多态:父类引用指向子类对象
Animal myCat = new Cat("Whiskers");
myDog.sleep();
// 输出: Buddy is sleeping. Zzz...
myDog.makeSound();
// 输出: Woof! Woof! (调用的是Dog类的实现)
myCat.sleep();
// 输出: Whiskers is sleeping. Zzz...
myCat.makeSound();
// 输出: Meow! Meow! (调用的是Cat类的实现)
}
}
6. 抽象类 vs 接口
这是一个初学者常见的困惑点。它们在概念上很相似,但有重要区别:
特性 | 抽象类 (Abstract Class) | 接口 (Interface) (Java 8+) |
---|---|---|
关键字 | abstract class | interface |
方法 | 可包含抽象方法和具体方法 | Java 8 前只能有抽象方法,之后可包含 default 和 static 方法 |
字段 | 可以有任何类型的字段(普通、静态、常量) | 字段默认是 public static final (常量) |
构造方法 | 有构造方法 | 没有构造方法 |
继承 | 类只能单继承一个抽象类 | 类可以实现多个接口 |
设计目的 | “是一个”(IS-A) 关系,表示本质 | “具有一种能力”(CAN-DO) 关系,表示行为 |
简单选择原则:
- 如果你想定义一些对象的基本本质(比如它们都是“动物”),并且需要包含一些公共的实现代码,用抽象类。
- 如果你想定义一些对象可以做什么的契约(比如“可飞行”、“可游泳”),并且不关心它们具体是什么,用接口。
7. 总结
abstract
关键字用于创建抽象类和抽象方法。- 抽象类是一个未完成的蓝图,不能实例化,只能被继承。
- 抽象方法只有声明没有实现,强制要求普通子类必须重写。
- 使用抽象的核心目的是定义规范,实现多态,提高代码的灵活性和可维护性。
- 抽象类通常用于建立 IS-A(是一个)关系,是代码重用的良好基础。
希望通过本篇让你对abstract关键字有了更深的理解
。