Java的抽象类的讲解

Java的抽象类的讲解

1.1抽象类概念

在⾯向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是⽤来描绘对象的,如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。

1.2定义抽象类是一种特殊的类,它不能被实例化(即不能创建对象)。它通常作为其他类的基类(父类)而存在,用于定义一组公共的接口和部分实现,强制要求其派生类(子类)必须遵循某种结构或实现某些特定方法。在面向对象编程(OOP)中,抽象类是实现抽象化和多态性的关键工具之一。

1.3抽象类的语法在Java中,⼀个类如果被 abstract 修饰称为抽象类,抽象类中被方法,抽象方法不⽤给出具体的实现体。

代码语言:javascript复制 // 抽象类:被abstract修饰的类

public abstract class Shape {

// 抽象⽅法:被abstract修饰的⽅法,没有⽅法体

abstract public void draw();

abstract void calcArea();

// 抽象类也是类,也可以增加普通⽅法和属性

public double getArea(){

return area;

}

}

// abstract 修饰的⽅法称为抽象方法

protected double area;

// ⾯积注:抽象类也是类,内部可以包含普通⽅法和属性,甚⾄构造⽅法

1.4抽象类的特性不能被实例化代码语言:javascript复制//这里假设这个抽象类类名为Animals

Animasl animal = new Animals();

//编译错误

//抽象类无法实例化这是抽象类最根本的特性。你不能使用 new 关键字来创建一个抽象类的对象。它的存在意义是“被继承”。

为什么? 因为它本身可能包含未实现的抽象方法,这些方法没有具体的函数体。创建一个不完整的对象是没有意义的,也是不允许的。

可以包含抽象方法

抽象方法是一种只有声明(方法签名)而没有实现(没有方法体)的方法。它使用 abstract 关键字进行修饰。代码语言:javascript复制 // 1. 抽象方法 (必须用 abstract,无方法体)

abstract void abstractMethod();作用:抽象方法在抽象类中定义了一个“契约”或“规范”,强制任何继承它的非抽象子类必须提供该方法的具体实现。这确保了所有子类都拥有某种特定的行为。

也可以包含普通方法

抽象类并非只能有抽象方法。它可以和普通类一样,拥有已经实现了的成员方法、属性、字段、构造函数等。代码语言:javascript复制 // 2. 普通的具体方法 (有方法体,子类可直接继承或重写)

void concreteMethod() {

System.out.println("我是一个已经实现的方法");

}好处:这允许你在抽象类中提供一些通用的功能实现,子类可以直接继承或重写这些方法,避免了代码重复,实现了代码复用。

这个是防止大家混淆,举了几个方法的例子

代码语言:javascript复制abstract class Example {

// 1. 抽象方法 (必须用 abstract,无方法体)

abstract void abstractMethod();

// 2. 普通的具体方法 (有方法体,子类可直接继承或重写)

void concreteMethod() {

System.out.println("我是一个已经实现的方法");

}

// 3. 静态方法 (属于类本身,有方法体)

static void staticMethod() {

System.out.println("我是一个静态方法");

}

// 4. 私有方法 (Java 9+,有方法体,通常用于辅助内部逻辑)

private void privateMethod() {

System.out.println("内部使用的私有方法");

}

}构造函数

抽象类虽然不能实例化,但可以拥有构造函数。这个构造函数在其子类被实例化时会被调用(通常通过 super() 在子类构造函数中调用),用于初始化抽象类中定义的字段或执行一些公共的初始化逻辑。比如下面就是一个抽象类,写的结构比较完善,让大家更好的理解抽象类。代码语言:javascript复制abstract class Employee {

// 所有员工都有的共同字段(由抽象类的构造函数初始化)

private String name;

private int id;

private double baseSalary; // 基本工资

// 抽象类的构造函数 - 用于初始化公共字段

public Employee(String name, int id, double baseSalary) {

this.name = name;

this.id = id;

this.baseSalary = baseSalary;

System.out.println("员工基本信息已初始化: " + name + " (ID: " + id + ")");

}

// 抽象方法:计算最终工资(不同岗位算法不同)

public abstract double calculateSalary();

// 普通方法:获取基本信息(所有子类都可使用)

public void displayBasicInfo() {

System.out.println("姓名: " + name + ", 工号: " + id + ", 基本工资: " + baseSalary);

}

// 获取基本工资(可能在计算最终工资时用到)

protected double getBaseSalary() {

return baseSalary;

}

}

// 具体子类:开发人员

class Developer extends Employee {

private double bonus; // 开发人员特有的奖金字段

// 子类构造函数

public Developer(String name, int id, double baseSalary, double bonus) {

// 调用父类构造函数初始化公共字段(name, id, baseSalary)

super(name, id, baseSalary);

this.bonus = bonus;

System.out.println("开发人员特有信息已初始化,奖金: " + bonus);

}

// 实现抽象方法:开发人员的工资计算方式

@Override

public double calculateSalary() {

return getBaseSalary() + bonus; // 基本工资 + 奖金

}

// 开发人员特有的方法

public void code() {

System.out.println("开发人员正在编码...");

}

}

// 具体子类:经理

class Manager extends Employee {

private double allowance; // 经理特有的津贴字段

// 子类构造函数

public Manager(String name, int id, double baseSalary, double allowance) {

// 调用父类构造函数初始化公共字段

super(name, id, baseSalary);

this.allowance = allowance;

System.out.println("经理特有信息已初始化,津贴: " + allowance);

}

// 实现抽象方法:经理的工资计算方式

@Override

public double calculateSalary() {

return getBaseSalary() + allowance; // 基本工资 + 津贴

}

// 经理特有的方法

public void manage() {

System.out.println("经理正在管理团队...");

}

}

// 测试类

public class CompanySystem {

public static void main(String[] args) {

System.out.println("=== 创建开发人员对象 ===");

Developer dev = new Developer("张三", 1001, 15000.0, 5000.0);

dev.displayBasicInfo();

System.out.println("最终工资: " + dev.calculateSalary());

dev.code();

System.out.println("\n=== 创建经理对象 ===");

Manager manager = new Manager("李四", 2001, 20000.0, 10000.0);

manager.displayBasicInfo();

System.out.println("最终工资: " + manager.calculateSalary());

manager.manage();

}

}继承

子类使用 extends 关键字来继承一个抽象类。如果一个子类也是抽象类,它可以不实现父抽象类的所有抽象方法。

如果一个子类是普通(具体)类,则必须实现(Override)其父抽象类中所有的抽象方法,否则编译器会报错。

抽象类必须被继承,并且继承后⼦类要重写⽗类中的抽象⽅法,否则⼦类也是抽象类,必须要使⽤abstract

修饰

6.不能被static,final,private修饰,因为抽象方法要被子类重写。

代码语言:javascript复制abstract class Example {

// 1. 抽象方法 (必须用 abstract,无方法体)

abstract void abstractMethod();

// 2. 普通的具体方法 (有方法体,子类可直接继承或重写)

void concreteMethod() {

System.out.println("我是一个已经实现的方法");

}

// 3. 静态方法 (属于类本身,有方法体)

static void staticMethod() {

System.out.println("我是一个静态方法");

}

// 4. 私有方法 (Java 9+,有方法体,通常用于辅助内部逻辑)

private void privateMethod() {

System.out.println("内部使用的私有方法");

}

}注意:

抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类⼀定是抽象类。抽象类中可以有构造⽅法,供⼦类创建对象时,初始化⽗类的成员变量。1.5抽象类的作用代码语言:javascript复制 抽象类的五大核心作用

1. 代码复用 (Code Reuse)作用:将多个相关类共有的属性和行为提取到抽象类中,子类可以直接继承使用,避免代码重复。

代码语言:javascript复制abstract class Vehicle {

private String brand;

private int maxSpeed;

// 公共方法,所有子类都可使用

public void startEngine() {

System.out.println("引擎启动中...");

}

public void stopEngine() {

System.out.println("引擎关闭中...");

}

}

class Car extends Vehicle {

// Car 自动拥有了 startEngine() 和 stopEngine() 方法

}

class Motorcycle extends Vehicle {

// Motorcycle 也自动拥有了这些方法

}强制规范与定义契约 (Enforcing Contracts)

作用:通过抽象方法,强制要求所有非抽象子类必须实现特定的方法,确保系统架构的一致性。代码语言:javascript复制abstract class DatabaseConnector {

// 强制子类必须实现连接方法

public abstract void connect();

public abstract void disconnect();

public abstract void executeQuery(String query);

}

class MySQLConnector extends DatabaseConnector {

@Override

public void connect() { System.out.println("连接MySQL数据库..."); }

@Override

public void disconnect() { System.out.println("断开MySQL连接..."); }

@Override

public void executeQuery(String query) { System.out.println("执行MySQL查询: " + query); }

}

// 任何新的数据库连接器都必须实现这三个方法实现多态 (Polymorphism)

作用:允许使用抽象类类型作为引用,在运行时动态指向不同的具体子类对象,实现同一接口的不同行为。代码语言:javascript复制abstract class Shape {

public abstract double calculateArea();

}

class Circle extends Shape {

private double radius;

public double calculateArea() { return Math.PI * radius * radius; }

}

class Rectangle extends Shape {

private double width, height;

public double calculateArea() { return width * height; }

}

// 使用多态

public class Test {

public static void main(String[] args) {

Shape shape1 = new Circle(5.0); // 指向Circle对象

Shape shape2 = new Rectangle(4.0, 6.0); // 指向Rectangle对象

System.out.println("圆形面积: " + shape1.calculateArea()); // 调用Circle的实现

System.out.println("矩形面积: " + shape2.calculateArea()); // 调用Rectangle的实现

}

}提供部分实现 (Partial Implementation)

作用:抽象类可以提供一些已经实现的方法,同时留下一些抽象方法让子类去完成,实现"模板方法"设计模式。代码语言:javascript复制abstract class Game {

// 已经实现的方法

public void initialize() {

System.out.println("游戏初始化完成");

}

public void start() {

initialize();

play(); // 调用抽象方法

end();

}

public void end() {

System.out.println("游戏结束");

}

// 抽象方法,子类必须实现具体的游戏逻辑

public abstract void play();

}

class Chess extends Game {

@Override

public void play() {

System.out.println("下国际象棋中...");

}

}

class Poker extends Game {

@Override

public void play() {

System.out.println("玩扑克牌中...");

}

}提高可维护性和扩展性 (Maintainability and Extensibility)

作用:当需要添加新功能时,只需创建新的子类继承抽象类并实现抽象方法即可,无需修改现有代码,符合"开闭原则"。代码语言:javascript复制// 现有系统

abstract class PaymentProcessor {

public abstract boolean processPayment(double amount);

}

class CreditCardProcessor extends PaymentProcessor {

public boolean processPayment(double amount) { /* 信用卡处理逻辑 */ }

}

class PayPalProcessor extends PaymentProcessor {

public boolean processPayment(double amount) { /* PayPal处理逻辑 */ }

}

// 未来扩展:添加新的支付方式无需修改现有代码

class CryptoProcessor extends PaymentProcessor {

public boolean processPayment(double amount) { /* 加密货币处理逻辑 */ }

}抽象类本⾝不能被实例化,要想使用,只能创建该抽象类的⼦类.然后让子类重写抽象类中的抽象方法.抽象类相当于多了⼀重编译器的校验.那使用场景是什么呢,使用抽象类的场景在实际工作不应该由父类完成,而应由子类完成.那么此时如果不小心误用成父类了,使用普通类编译器是不会报错的.但是父类是抽象类就会在实例化的时候提示错误,让我们尽早发现问题.

相关尊享内容

瑞星杀毒软件
mobile365体育

瑞星杀毒软件

📅 10-23 👑 197
鳙品种遗传改良研究现状及进展
365app下载安装官方免费下载

鳙品种遗传改良研究现状及进展

📅 09-01 👑 685
行的五笔编码和拆分图解
365bet游戏下载

行的五笔编码和拆分图解

📅 09-29 👑 133