跳转至

接口与抽象类

写过 TypeScript 的 interface?Java 的接口你会秒懂。但 Java 8 给接口加了默认方法,能力更强。

接口 interface

interface Flyable {
    void fly();           // 默认就是 public abstract,可省略
}

interface Swimmer {
    default void swim() {     // JDK 8:接口可以有默认实现
        System.out.println("游泳中...");
    }
}

class Duck implements Flyable, Swimmer {   // 实现多个接口
    @Override
    public void fly() { }
}

关键:Java 类只能 extends 一个父类(单继承),但可以 implements 多个接口——这就是 Java 的"多继承"替代方案。这也是 Spring 里大量用接口的原因。

接口 vs 抽象类

接口 interface 抽象类 abstract class
能 new 吗 不能 不能
字段 只能是常量 普通字段
方法 抽象 + default(JDK8) 抽象 + 具体方法
继承 可实现多个 只能继承一个
对标前端 TS 的 interface 抽象程度更高的父类

什么时候用哪个

  • 用接口:定义"能力/契约"。比如 Comparable(可比较)、Runnable(可运行)。Spring 服务层通常定义 UserService 接口 + UserServiceImpl 实现。
  • 用抽象类:多个子类有共享的字段和具体方法,只是个别行为不同。比如 AbstractController
classDiagram
    class Flyable { <<interface>> +fly() }
    class Swimmer { <<interface>> +swim() }
    class Duck
    Duck ..|> Flyable : implements
    Duck ..|> Swimmer : implements
    class Shape { <<abstract>> +area()* }
    class Circle { +area() }
    Circle --|> Shape : extends

完整可运行示例

package com.javaglm.language.ch09;

/**
 * 第 09 章 · 接口与抽象类。
 * 接口(interface)对标 TS 的 interface,但 Java 8 的接口还能有 default 默认实现。
 * 一个类可以实现多个接口——这就是 Java 替代"多继承"的方案。
 * 抽象类(abstract class):不能 new,介于普通类和接口之间。
 */
public class InterfaceDemo {

    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.fly();          // 实现的抽象方法
        duck.swim();         // 接口的 default 方法(没重写就直接用)

        // 接口类型引用 = 多态
        Flyable f = new Duck();
        f.fly();

        // 抽象类:用子类实例化
        Shape circle = new Circle(2);
        System.out.println("圆面积 = " + circle.area());
    }
}

/** 接口:方法默认 public abstract(不用写也行)。 */
interface Flyable {
    void fly();
}

/** 接口的 default 方法:JDK 8 起接口可以带默认实现。 */
interface Swimmer {
    default void swim() {
        System.out.println("游泳中...");
    }
}

/** 一个类可以实现多个接口——这是 Java 做不到多继承的替代方案。 */
class Duck implements Flyable, Swimmer {
    @Override
    public void fly() {
        System.out.println("鸭子飞起来了");
    }
}

/** 抽象类:不能 new,可以有抽象方法(子类必须实现)和具体方法。 */
abstract class Shape {
    abstract double area();   // 抽象方法,没有方法体
}

class Circle extends Shape {
    private double r;
    Circle(double r) { this.r = r; }
    @Override
    double area() { return Math.PI * r * r; }
}

:octicons-arrow-left-16: 上一章:封装·继承·多态 | 下一章:包与访问修饰符