编程自学指南:java程序设计开发,Java 抽象类详解
一、课程信息
学习目标
- 理解抽象类的概念、作用及适用场景
- 掌握抽象类的定义、继承与抽象方法实现
- 区分抽象类与普通类、接口的核心差异
- 能通过抽象类设计可扩展的代码结构
二、课程导入:从生活到代码
🌰 生活案例:交通工具的「移动」行为
- 飞机、汽车、轮船都有「移动」行为,但实现方式不同
- 抽象:定义「移动」为通用行为,但具体实现由子类决定
❌ 无抽象类的代码问题
class Airplane {
void move() { System.out.println("飞机飞行"); }
}
class Car {
void move() { System.out.println("汽车行驶"); }
}
class Ship {
void move() { System.out.println("轮船航行"); }
}
// 问题:重复定义 move(),无法统一管理
✅ 抽象类解决方案
abstract class Vehicle { // 抽象类
abstract void move(); // 抽象方法(强制子类实现)
void start() { // 具体方法(子类可复用)
System.out.println("启动引擎");
}
}
class Airplane extends Vehicle {
@Override void move() { /* 具体实现 */ }
}
三、抽象类基础:定义与语法
1. 抽象类的定义
- 关键字:
abstract class
- 特点:包含抽象方法(无方法体)或为模板类
- 规则:不能直接实例化,必须通过子类继承
2. 抽象方法
- 关键字:
abstract
,无{}
方法体 - 强制约束:子类必须重写(除非子类也是抽象类)
3. 完整案例:动物抽象类
abstract class Animal {
private String name;
public Animal(String name) { this.name = name; } // 构造方法
abstract void makeSound(); // 抽象方法(子类必须实现)
// 具体方法(子类可直接复用)
void eat() {
System.out.println(name + " 正在进食");
}
}
// 子类实现
class Cat extends Animal {
public Cat(String name) { super(name); }
@Override void makeSound() { // 必须重写
System.out.println("喵喵~");
}
}
public class Test {
public static void main(String[] args) {
Animal cat = new Cat("咪咪"); // 多态调用
cat.makeSound(); // 输出:喵喵~
cat.eat(); // 输出:咪咪 正在进食
}
}
🔥 初学者必看:抽象类的「强制契约」
如果子类不实现抽象方法:
class Dog extends Animal { // 编译报错!
// 未实现 makeSound()
}
// 错误提示:The type Dog must implement the inherited abstract method Animal.makeSound()
四、抽象类的核心特性
特性 1:不能实例化
Animal animal = new Animal("无名氏"); // 编译错误!
// 错误提示:Cannot instantiate the type Animal
特性 2:构造方法的存在
- 抽象类可以有构造方法,供子类初始化使用
- 子类构造方法必须调用父类构造(
super()
)
abstract class Person {
protected int age;
public Person(int age) { this.age = age; }
}
class Student extends Person {
public Student(int age) {
super(age); // 必须调用父类构造
}
}
特性 3:包含具体方法
- 抽象类可以同时包含抽象方法和具体方法
- 子类可复用具体方法,只重写抽象方法
abstract class Shape {
abstract double area(); // 抽象方法(计算面积)
void showArea() { // 具体方法(通用逻辑)
System.out.println("面积:" + area());
}
}
class Circle extends Shape {
private double radius;
@Override double area() { return Math.PI * radius * radius; }
}
// 使用:
new Circle(5).showArea(); // 复用 showArea()
五、抽象类 vs 普通类 vs 接口(对比表格)
特性 | 抽象类 | 普通类 | 接口 |
---|---|---|---|
能否实例化 | ❌ 不能 | ✅ 能 | ❌ 不能 |
抽象方法 | ✅ 可以有 | ❌ 不能 | ✅ 隐式抽象方法 |
具体方法 | ✅ 可以有 | ✅ 必须有 | ❌ Java8 前不能 |
成员变量 | 可以有普通变量 | 普通变量 | 只能是 public static final |
构造方法 | ✅ 可以有(供子类调用) | ✅ 必须有 | ❌ 不能 |
继承 / 实现 | 单继承(extends ) | 单继承 | 多实现(implements ) |
设计目的 | 模板设计(部分实现,部分抽象) | 具体对象 | 行为规范(纯抽象) |
📌 记忆口诀:
抽象类是「半成品」,接口是「契约书」
抽象类有构造能存状态,接口全是行为规范
六、抽象类实战案例
案例 1:图形计算抽象类
abstract class Graphic {
abstract double getArea(); // 抽象方法(计算面积)
abstract double getPerimeter(); // 抽象方法(计算周长)
// 具体方法:打印图形信息
void printInfo() {
System.out.println("面积:" + getArea() +
", 周长:" + getPerimeter());
}
}
class Rectangle extends Graphic {
private double width, height;
public Rectangle(double w, double h) { width=w; height=h; }
@Override double getArea() { return width * height; }
@Override double getPerimeter() { return 2*(width+height); }
}
public class TestGraphic {
public static void main(String[] args) {
Graphic rect = new Rectangle(3, 4);
rect.printInfo();
// 输出:面积:12.0, 周长:14.0
}
}
案例 2:员工工资计算抽象类
abstract class Employee {
protected String name;
public Employee(String name) { this.name = name; }
abstract double calculateSalary(); // 抽象方法(计算工资)
// 具体方法:打印工资单
void printPaySlip() {
System.out.println(name + " 的工资:" + calculateSalary());
}
}
class Developer extends Employee {
private int hours;
public Developer(String name, int hours) {
super(name);
this.hours = hours;
}
@Override double calculateSalary() {
return hours * 500; // 时薪500
}
}
public class TestEmployee {
public static void main(String[] args) {
new Developer("张三", 160).printPaySlip();
// 输出:张三 的工资:80000.0
}
}
七、课堂练习
练习 1:交通工具抽象类
需求:
- 定义抽象类
Vehicle
,包含抽象方法move()
和具体方法stop()
- 子类
Bike
(自行车)、Train
(火车)实现move()
- 测试:创建子类对象,调用
move()
和stop()
参考代码:
abstract class Vehicle {
abstract void move();
void stop() { System.out.println("已停车"); }
}
class Bike extends Vehicle {
@Override void move() { System.out.println("自行车骑行"); }
}
// 测试:new Bike().move(); // 输出:自行车骑行
练习 2:考试评分抽象类
需求:
- 抽象类
Exam
包含抽象方法getScore()
(获取分数) - 具体方法
judge()
:根据分数判断等级(>90 = 优秀,80-90 = 良好) - 子类
MathExam
、EnglishExam
实现getScore()
提示:在 judge()
中调用抽象方法 getScore()
八、常见误区与注意事项
误区 1:抽象类必须包含抽象方法
✅ 错误!抽象类可以没有抽象方法(用于限制实例化)
abstract class Tool { // 无抽象方法
void use() { System.out.println("使用工具"); }
}
// 作用:禁止直接创建 Tool 对象,强制通过子类扩展
误区 2:抽象方法可以有方法体
❌ 错误!抽象方法必须没有方法体
abstract void run(); // 正确
abstract void run() {} // 编译错误!
误区 3:子类必须实现所有抽象方法
✅ 正确!除非子类也是抽象类
abstract class Animal {
abstract void eat();
}
abstract class Pet extends Animal {
// 可以不实现 eat(),因为 Pet 是抽象类
}
九、课程总结
核心知识点图谱
抽象类 → 关键字 abstract
→ 包含抽象方法(强制子类实现)和具体方法(代码复用)
→ 不能实例化,必须通过子类继承
→ 适用场景:模板设计(如通用算法 + 差异化实现)
抽象类的三大作用
- 代码复用:通过具体方法减少重复代码
- 强制约束:通过抽象方法规范子类行为
- 多态基础:父类引用指向子类对象,实现动态绑定
记忆口诀:
抽象类,像模板,抽象方法强制管
构造方法不能少,子类必须来实现
代码复用又规范,设计模式常相见
十、课后作业(必做 + 选做)
必做 1:形状抽象类(面积与周长)
- 定义抽象类
Shape
,包含抽象方法area()
和perimeter()
- 子类
Square
(正方形)、Triangle
(三角形)实现这两个方法 - 测试:创建对象并打印面积和周长
必做 2:动物声音抽象类
- 抽象类
Animal
包含抽象方法sound()
和具体方法info()
(打印声音) - 子类
Dog
、Bird
实现sound()
- 测试:
new Dog().info()
输出「汪汪!」
选做:游戏角色抽象类
- 抽象类
GameCharacter
包含抽象方法attack()
和具体方法die()
(播放死亡动画) - 子类
Warrior
(战士)、Mage
(法师)实现不同的attack()
逻辑 - 扩展:添加
hp
属性,在die()
中判断hp <=0
时触发动画