Java 抽象类 知识点

  1. 定义与语法细节

· 抽象类:使用 abstract class 定义,如 public abstract class Animal { }

· 抽象方法:使用 abstract 修饰,没有方法体(直接以分号结尾)。

public abstract void makeSound();

· 类中可包含:

· 抽象方法(强制子类实现)

· 非抽象方法(有具体实现)

· 成员变量(可以是 private、protected、public、static、final 等)

· 构造方法(虽然不能实例化,但供子类调用)

· 静态代码块、实例代码块


  1. 继承与实现规则

· 子类通过 extends 继承抽象类。

· 必须实现所有抽象方法,否则子类也必须声明为 abstract。

· 子类可以重写父类的非抽象方法(普通方法也可以被重写)。

· 一个子类只能继承一个抽象类(单继承)。

· 抽象类可以实现接口(使用 implements),且可以不实现接口中的方法(交由具体子类实现)。


  1. 构造方法与初始化

· 抽象类有构造方法,但不能直接 new。

· 子类构造方法中必须通过 super(...) 调用父类构造方法(隐式或显式)。

· 初始化顺序:父类静态块 → 子类静态块 → 父类实例块 → 父类构造方法 → 子类实例块 → 子类构造方法。


  1. 关键限制(与修饰符的互斥)

修饰符组合 是否允许 原因

abstract + final ❌ 方法/类均不行 final 禁止重写/继承,与抽象矛盾

abstract + private ❌ 方法 private 不能被子类访问,无法重写

abstract + static ❌ 方法 静态方法属于类,不能重写

abstract + native ❌ 方法 native 已有实现(非Java),与抽象冲突


  1. 与接口的细致对比(补充要点)

· 字段:接口字段默认 public static final;抽象类无此限制。

· 方法可见性:抽象类可以有 protected、private 方法;接口方法(Java 8前)只能是 public。

· 状态:抽象类可以维护可变状态(非 final 字段);接口通常无状态(除非定义 static final 常量)。

· Java 8+ 接口新特性:default 和 static 方法,但依然不能有实例字段。

· 选择原则:需要共享代码、状态 → 抽象类;定义能力(多实现) → 接口。


  1. 典型应用模式

· 模板方法模式

抽象类中定义骨架方法(final 防止篡改),调用一系列抽象方法或钩子方法。

```java

public abstract class DataParser {

public final void parse() {

readData();

processData();

writeData();

}

protected abstract void readData();

protected abstract void processData();

protected void writeData() { } // 钩子,默认空实现

}

```

· 工厂方法模式:抽象类定义创建对象的抽象方法,子类具体实现。


  1. 常见误区与面试题

· 误区:抽象类不能有构造方法 ❌ (实际可以有,用于初始化父类字段)

· 误区:抽象方法不能有主体,但可以有 {} ❌ (必须 ; 结尾,不能有大括号)

· 误区:abstract 类中只能有抽象方法 ❌ (可以有具体方法)

· 面试题:为什么抽象类可以 main 方法?

答:main 是静态方法,与实例化无关,可以正常执行,但需要子类或间接调用。

· 面试题:abstract 类能否实现接口且不实现方法?

答:可以,作为抽象类,它可以把接口方法继续声明为抽象方法,留给子类实现。


  1. 代码示例(完整演示)

```java

public abstract class Vehicle {

protected String brand;

public Vehicle(String brand) {

this.brand = brand;

}

public abstract void start(); // 抽象方法

public void showBrand() { // 具体方法

System.out.println("Brand: " + brand);

}

}

public class Car extends Vehicle {

public Car(String brand) {

super(brand);

}

@Override

public void start() {

System.out.println(brand + " car starts with key.");

}

}

// 使用

Vehicle v = new Car("Toyota");

v.start(); // Toyota car starts with key.

v.showBrand(); // Brand: Toyota

```

相关推荐
say_fall2 小时前
滑动窗口算法
数据结构·c++·算法
落羽的落羽2 小时前
【算法札记】练习 | Week1
linux·服务器·c++·人工智能·python·算法·机器学习
踏着七彩祥云的小丑2 小时前
Python——排序
开发语言·python
c++圈来了个新人2 小时前
C++类和对象(上)
c语言·开发语言·数据结构·c++·考研
人道领域2 小时前
【LeetCode刷题日记】15.三数之和(梦破碎的地方)
算法·leetcode·面试
️是782 小时前
信息奥赛一本通(4005:【GESP2306一级】时间规划)
数据结构·c++·算法
tankeven2 小时前
HJ174 交换到最大
c++·算法
xyq20242 小时前
SQL CREATE INDEX
开发语言
Дерек的学习记录2 小时前
Unreal Eangie 5:蓝图编程
开发语言·学习·ue5