← 返回首页
🏗️

Java抽象类详解:定义、继承与使用

📂 java ⏱ 5 min 933 words

Java抽象类详解:定义、继承与使用

概述

抽象类(Abstract Class)是不能被实例化的类,用于定义一组相关类的共同特征。抽象类可以包含抽象方法和普通方法,是实现多态和代码复用的重要机制。

1. 抽象类的定义

基本语法

public abstract class Animal {
    protected String name;
    protected int age;
    
    // 构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 抽象方法(没有方法体)
    public abstract void sound();
    public abstract void move();
    
    // 普通方法(有方法体)
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    
    public void sleep() {
        System.out.println(name + "正在睡觉");
    }
    
    public void display() {
        System.out.println("名字: " + name + ", 年龄: " + age);
    }
}

// 抽象类不能被实例化
// Animal animal = new Animal("Tom", 3);  // 编译错误

2. 继承抽象类

public class Dog extends Animal {
    private String breed;
    
    public Dog(String name, int age, String breed) {
        super(name, age);  // 调用父类构造方法
        this.breed = breed;
    }
    
    @Override
    public void sound() {
        System.out.println(name + "汪汪汪");
    }
    
    @Override
    public void move() {
        System.out.println(name + "跑来跑去");
    }
    
    public void fetch() {
        System.out.println(name + "正在捡球");
    }
    
    @Override
    public void display() {
        super.display();
        System.out.println("品种: " + breed);
    }
}

public class Cat extends Animal {
    public Cat(String name, int age) {
        super(name, age);
    }
    
    @Override
    public void sound() {
        System.out.println(name + "喵喵喵");
    }
    
    @Override
    public void move() {
        System.out.println(name + "轻手轻脚地走");
    }
    
    public void scratch() {
        System.out.println(name + "正在抓老鼠");
    }
}

// 测试
public class AbstractClassTest {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财", 3, "金毛");
        Cat cat = new Cat("咪咪", 2);
        
        dog.display();
        dog.sound();
        dog.move();
        dog.eat();
        dog.fetch();
        
        System.out.println();
        
        cat.display();
        cat.sound();
        cat.move();
        cat.eat();
        cat.scratch();
    }
}

3. 抽象类与多态

public abstract class Shape {
    protected String name;
    
    public Shape(String name) {
        this.name = name;
    }
    
    // 抽象方法
    public abstract double area();
    public abstract double perimeter();
    
    // 普通方法
    public void display() {
        System.out.println("形状: " + name);
        System.out.println("面积: " + String.format("%.2f", area()));
        System.out.println("周长: " + String.format("%.2f", perimeter()));
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        super("圆形");
        this.radius = radius;
    }
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

public class Rectangle extends Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        super("矩形");
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double area() {
        return width * height;
    }
    
    @Override
    public double perimeter() {
        return 2 * (width + height);
    }
}

public class Triangle extends Shape {
    private double a, b, c;
    
    public Triangle(double a, double b, double c) {
        super("三角形");
        this.a = a;
        this.b = b;
        this.c = c;
    }
    
    @Override
    public double area() {
        double s = (a + b + c) / 2;
        return Math.sqrt(s * (s - a) * (s - b) * (s - c));
    }
    
    @Override
    public double perimeter() {
        return a + b + c;
    }
}

// 多态应用
public class ShapeTest {
    public static void main(String[] args) {
        Shape[] shapes = {
            new Circle(5),
            new Rectangle(4, 6),
            new Triangle(3, 4, 5)
        };
        
        for (Shape shape : shapes) {
            shape.display();
            System.out.println();
        }
    }
}

4. 模板方法模式

public abstract class DataProcessor {
    // 模板方法
    public final void process() {
        readData();
        processData();
        writeData();
        log();
    }
    
    // 抽象方法(子类必须实现)
    protected abstract void readData();
    protected abstract void processData();
    protected abstract void writeData();
    
    // 普通方法(可以被重写)
    protected void log() {
        System.out.println("数据处理完成");
    }
}

public class CSVDataProcessor extends DataProcessor {
    @Override
    protected void readData() {
        System.out.println("读取CSV文件");
    }
    
    @Override
    protected void processData() {
        System.out.println("处理CSV数据");
    }
    
    @Override
    protected void writeData() {
        System.out.println("写入CSV文件");
    }
    
    @Override
    protected void log() {
        System.out.println("CSV数据处理完成");
    }
}

public class JSONDataProcessor extends DataProcessor {
    @Override
    protected void readData() {
        System.out.println("读取JSON文件");
    }
    
    @Override
    protected void processData() {
        System.out.println("处理JSON数据");
    }
    
    @Override
    protected void writeData() {
        System.out.println("写入JSON文件");
    }
}

// 测试
public class TemplateMethodTest {
    public static void main(String[] args) {
        DataProcessor csvProcessor = new CSVDataProcessor();
        csvProcessor.process();
        
        System.out.println();
        
        DataProcessor jsonProcessor = new JSONDataProcessor();
        jsonProcessor.process();
    }
}

5. 抽象类与接口的区别

抽象类的特点

  1. 可以有构造方法
  2. 可以有成员变量
  3. 可以有普通方法
  4. 只能继承一个抽象类
  5. 访问修饰符可以是任意的

接口的特点

  1. 不能有构造方法
  2. 只能有常量
  3. 可以有默认方法和静态方法
  4. 可以实现多个接口
  5. 默认是public修饰
// 抽象类
public abstract class AbstractClass {
    protected int value;
    
    public AbstractClass(int value) {
        this.value = value;
    }
    
    public abstract void method1();
    
    public void method2() {
        System.out.println("普通方法");
    }
}

// 接口
public interface Interface {
    int CONSTANT = 10;
    
    void method1();
    
    default void method2() {
        System.out.println("默认方法");
    }
    
    static void method3() {
        System.out.println("静态方法");
    }
}

// 类可以继承一个抽象类,实现多个接口
public class MyClass extends AbstractClass implements Interface {
    public MyClass(int value) {
        super(value);
    }
    
    @Override
    public void method1() {
        System.out.println("实现的方法");
    }
}

6. 实际应用示例

员工管理系统

public abstract class Employee {
    protected String name;
    protected double baseSalary;
    
    public Employee(String name, double baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }
    
    // 抽象方法
    public abstract double calculateSalary();
    public abstract String getRole();
    
    // 普通方法
    public void display() {
        System.out.println("姓名: " + name);
        System.out.println("角色: " + getRole());
        System.out.println("基本工资: " + baseSalary);
        System.out.println("总工资: " + calculateSalary());
        System.out.println();
    }
    
    public boolean isHigherPaid(Employee other) {
        return this.calculateSalary() > other.calculateSalary();
    }
}

public class Developer extends Employee {
    private double bonus;
    
    public Developer(String name, double baseSalary, double bonus) {
        super(name, baseSalary);
        this.bonus = bonus;
    }
    
    @Override
    public double calculateSalary() {
        return baseSalary + bonus;
    }
    
    @Override
    public String getRole() {
        return "开发工程师";
    }
}

public class Manager extends Employee {
    private double teamSize;
    private double teamBonus;
    
    public Manager(String name, double baseSalary, double teamSize, double teamBonus) {
        super(name, baseSalary);
        this.teamSize = teamSize;
        this.teamBonus = teamBonus;
    }
    
    @Override
    public double calculateSalary() {
        return baseSalary + (teamBonus * teamSize);
    }
    
    @Override
    public String getRole() {
        return "经理";
    }
}

public class EmployeeTest {
    public static void main(String[] args) {
        Employee dev = new Developer("张三", 10000, 5000);
        Employee manager = new Manager("李四", 15000, 5, 2000);
        
        dev.display();
        manager.display();
        
        if (dev.isHigherPaid(manager)) {
            System.out.println(dev.name + "工资更高");
        } else {
            System.out.println(manager.name + "工资更高");
        }
    }
}

7. 最佳实践

  1. 使用抽象类定义模板:当多个类有共同结构时,使用抽象类
  2. 抽象方法数量适中:抽象方法太多会导致实现复杂
  3. 使用模板方法模式:固定算法骨架,让子类实现具体步骤
  4. 合理使用构造方法:抽象类可以有构造方法供子类调用
  5. 文档化抽象方法:清楚地文档化抽象方法的契约

总结

抽象类是Java面向对象编程的重要特性。通过抽象类,可以定义类的共同特征、实现代码复用、支持多态。理解抽象类的使用规则和最佳实践,对于设计良好的面向对象程序至关重要。