在 Java 中,“抽象” 是面向对象编程的核心思想之一,它的本质是忽略次要细节,提取共同特征,专注于核心本质。简单来说,就是把具体事物中具有普遍性的特征(属性和行为)提炼出来,形成一个通用的概念框架,而不关注具体实现。

比如:“动物” 就是一个抽象概念,它提取了 “猫、狗、鸟” 等具体动物的共同特征(会呼吸、会移动),但不特指某一种具体动物。在 Java 中,抽象通过抽象类接口两种方式实现。

一、抽象类(Abstract Class)

抽象类是用abstract修饰的类,它不能被实例化(无法创建对象),只能作为父类被继承。抽象类中可以包含:

  • 抽象方法(用abstract修饰,只有方法声明,没有方法体);
  • 普通方法(有完整的方法体实现);
  • 成员变量和构造方法。

示例

// 抽象类:提取"动物"的共同特征
abstract class Animal {
    // 成员变量
    String name;
    
    // 构造方法
    public Animal(String name) {
        this.name = name;
    }
    
    // 抽象方法:所有动物都会叫,但具体叫声不同(延迟到子类实现)
    public abstract void bark();
    
    // 普通方法:所有动物都有相同的呼吸方式(直接实现)
    public void breathe() {
        System.out.println(name + "在呼吸");
    }
}

// 子类继承抽象类,必须实现所有抽象方法
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    
    // 实现抽象方法:具体的"叫"
    @Override
    public void bark() {
        System.out.println(name + "汪汪叫");
    }
}

二、接口(Interface)

接口是用interface声明的特殊类型,它更纯粹地体现抽象,同样不能被实例化,只能被类实现(implements)。接口中可以包含:

  • 抽象方法(JDK8 之前,默认public abstract);
  • 默认方法(JDK8+,用default修饰,有方法体,子类可重写);
  • 静态方法(JDK8+,用static修饰,属于接口本身);
  • 常量(默认public static final)。

示例

// 接口:定义"会飞"的行为规范
interface Flyable {
    // 抽象方法:飞的行为(具体实现交给子类)
    void fly();
    
    // 默认方法:通用的起飞动作
    default void takeOff() {
        System.out.println("准备起飞...");
    }
}

// 类实现接口,必须实现所有抽象方法
class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟扇动翅膀飞行");
    }
}

class Plane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机靠引擎飞行");
    }
}

三、抽象类和接口的核心区别

维度 抽象类(Abstract Class) 接口(Interface)
继承 / 实现方式 子类用extends继承,单继承 类用implements实现,多实现
方法类型 可包含抽象方法、普通方法、静态方法 JDK8 + 可包含抽象方法、默认方法、静态方法
成员变量 可包含任意成员变量(普通变量、常量) 只能包含常量(默认public static final
构造方法 有构造方法(供子类调用) 无构造方法
设计意图 体现 **"is-a" 关系 **(继承,强调共性) 体现 **"like-a" 关系 **(实现,强调能力)

四、使用场景选择

  1. 优先用抽象类的场景

        当需要提取类之间的共性特征(包括属性和方法实现),且这些类属于同一类别的 “父子关系” 时。

        例如:Animal(抽象类)与DogCat(子类),它们都是 “动物”,共享 “呼吸” 等基础方法,同时各自实现 “叫” 的具体方式。

      2.优先用接口的场景

        当需要定义一种行为规范或能力,且该能力可被不同类别的对象实现时。
        例如:Flyable(接口)可被Bird(动物)、Plane(机械)、Superman(人类)实现,它们不属于同一类别,但都具备 “飞” 的能力。

        3.实际开发中的组合使用

        一个类可以继承一个抽象类(获取基础共性),同时实现多个接口(扩展不同能力)。
        例如:Penguin类继承Animal(抽象类),同时实现Swimmable(接口)——“企鹅是动物,且会游泳”。

总结

  • 抽象是提炼共性、忽略细节的思想,抽象类和接口是其具体实现方式。
  • 抽象类侧重 **“是什么”(定义事物的本质),接口侧重“能做什么”**(定义行为规范)。
  • 设计时需根据类之间的关系(父子关系 / 能力扩展)选择合适的抽象方式,两者并非互斥,常结合使用。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐