Skip to content

接口

概述

接口(Interface)是 Java 中定义能力契约的一种类型:它只声明「能做什么」(方法签名),而不关心「怎么做」(不包含方法体,除非使用 default/static 实现)。类通过 implements 关键字实现接口,并必须提供接口中所有抽象方法的实现。一个类可以实现多个接口,从而具备多种能力,这是 Java 实现「多继承」效果的主要方式。接口类型的引用可以指向任意实现类对象,与 多态 结合,实现「面向接口编程」,提高可扩展性和解耦。

通俗理解:接口是一份「能力清单」——规定实现类必须提供哪些方法;谁实现了这份清单,谁就可以被当作该接口类型使用。接口与 抽象类 都能表达抽象与多态,但接口更侧重「契约」、无状态,且支持多实现。

前置建议

已掌握 继承多态抽象类,理解方法重写与「父类/抽象类引用指向子类对象」。


为什么需要接口

  • 定义能力契约:只声明方法签名,不关心实现细节,调用方只依赖「能调什么」,不依赖具体类。
  • 实现多「能力」:Java 类只能单继承,但可以实现多个接口,从而同时具备多种角色(如「可比较」「可序列化」「可关闭」)。
  • 解耦与可替换:依赖接口而非具体实现类,便于替换实现(如测试时注入 Mock、切换不同数据库驱动)。
  • 与抽象类的分工:接口无实例字段、无构造方法,纯「行为契约」;抽象类可有状态和部分实现,适合「是一种」的层次。需要多继承能力或纯契约时优先用接口。

基本语法

声明接口

使用 interface 关键字,方法默认为 public abstract(可省略),不能有方法体(JDK 8 前);从 JDK 8 起可包含 defaultstatic 方法并带实现。

java
// 接口中的方法默认就是 public abstract,无需写修饰符
public interface Drawable {
    void draw();   // 等价于 public abstract void draw();
}

实现接口

类使用 implements 实现接口,必须实现接口中所有抽象方法(未实现的 default 方法可选重写)。

java
public class Circle implements Drawable {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a circle with radius " + radius);
    }
}

// 接口引用指向实现类对象,多态
Drawable d = new Circle(3.0);
d.draw();   // Drawing a circle with radius 3.0

注意

实现接口时,实现方法的访问权限不能比接口中的更严格。接口方法默认为 public,因此实现类中的实现也必须是 public

多实现

一个类可以同时实现多个接口,用逗号分隔;必须实现每个接口中的全部抽象方法。

java
public interface Drawable {
    void draw();
}

public interface Resizable {
    void resize(double scale);
}

public class Rectangle implements Drawable, Resizable {
    private double width, height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a rectangle " + width + "x" + height);
    }

    @Override
    public void resize(double scale) {
        this.width *= scale;
        this.height *= scale;
    }
}

// 既可当作 Drawable,也可当作 Resizable
Drawable d = new Rectangle(2, 3);
Resizable r = new Rectangle(2, 3);
d.draw();
r.resize(1.5);

接口的成员

成员类型说明与语法
抽象方法无方法体,实现类必须实现;默认 public abstract
常量public static final 声明,可省略修饰符(默认即如此)
default 方法JDK 8+,带方法体,实现类可不重写,用于接口演进
static 方法JDK 8+,带方法体,通过接口名直接调用

常量

接口中的字段默认是 public static final,即常量,通常用大写命名。

java
public interface Config {
    int MAX_SIZE = 100;                    // 等价于 public static final int MAX_SIZE = 100;
    String DEFAULT_ENCODING = "UTF-8";
}

// 使用:Config.MAX_SIZE、Config.DEFAULT_ENCODING

default 方法(JDK 8+)

为接口增加 default 方法可提供默认实现,已有实现类不必强制重写,便于接口向后扩展。

java
public interface Greeter {
    void sayHello(String name);   // 抽象方法,实现类必须实现

    // default 方法:有默认实现,实现类可选重写
    default void sayBye() {
        System.out.println("Goodbye!");
    }
}

public class SimpleGreeter implements Greeter {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello, " + name);
    }
    // 未重写 sayBye(),将使用接口中的默认实现
}

SimpleGreeter g = new SimpleGreeter();
g.sayHello("Java");   // Hello, Java
g.sayBye();           // Goodbye!

static 方法(JDK 8+)

接口中可以定义 static 方法,通过接口名调用,不能通过实现类实例调用(与类的静态方法一致)。

java
public interface MathUtil {
    static int add(int a, int b) {
        return a + b;
    }
}

int sum = MathUtil.add(1, 2);   // 3,通过接口名调用

接口继承接口

接口可以继承多个其他接口(用 extends),从而组合多份契约;实现类只需实现最终接口中的全部抽象方法。

java
public interface Drawable {
    void draw();
}

public interface Colorable {
    void setColor(String color);
}

// 接口多继承:具备 draw + setColor 的契约
public interface DrawableAndColorable extends Drawable, Colorable {
}

public class ColoredCircle implements DrawableAndColorable {
    private double radius;
    private String color = "black";

    public ColoredCircle(double radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a " + color + " circle, radius " + radius);
    }

    @Override
    public void setColor(String color) {
        this.color = color;
    }
}

使用示例

示例 1:面向接口编程(多态)

方法参数和返回值使用接口类型,调用方可以传入任意实现类,便于扩展和测试。

java
public interface Logger {
    void log(String message);
}

public class ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("[CONSOLE] " + message);
    }
}

public class FileLogger implements Logger {
    @Override
    public void log(String message) {
        // 实际可写入文件,此处仅示例
        System.out.println("[FILE] " + message);
    }
}

// 面向接口编程:不依赖具体 Logger 实现
public class Service {
    private final Logger logger;

    public Service(Logger logger) {
        this.logger = logger;
    }

    public void doWork() {
        logger.log("Service started.");
        // ... 业务逻辑
        logger.log("Service finished.");
    }
}

// 使用:可注入不同实现
Service s1 = new Service(new ConsoleLogger());
Service s2 = new Service(new FileLogger());
s1.doWork();   // 输出到控制台
s2.doWork();   // 输出到「文件」

示例 2:多实现表达多种能力

一个类实现多个接口,在不同场景下被当作不同「角色」使用。

java
public interface Runnable {
    void run();
}

public interface Swimmable {
    void swim();
}

public class Duck implements Runnable, Swimmable {
    @Override
    public void run() {
        System.out.println("Duck runs on land.");
    }

    @Override
    public void swim() {
        System.out.println("Duck swims in water.");
    }
}

Duck duck = new Duck();
Runnable r = duck;
Swimmable s = duck;
r.run();    // Duck runs on land.
s.swim();   // Duck swims in water.

示例 3:接口中的 default 方法(JDK 8+)

用 default 方法在接口中提供通用逻辑,减少实现类重复代码。

java
public interface ListFormatter {
    String format(java.util.List<String> list);   // 抽象方法:如何格式化由实现类决定

    // default:提供通用「带标题」的格式,实现类可直接使用或重写
    default String formatWithTitle(String title, java.util.List<String> list) {
        return title + ":\n" + format(list);
    }
}

public class CommaFormatter implements ListFormatter {
    @Override
    public String format(java.util.List<String> list) {
        return String.join(", ", list);
    }
}

ListFormatter f = new CommaFormatter();
String result = f.formatWithTitle("Items", java.util.List.of("A", "B", "C"));
// Items:
// A, B, C

接口与抽象类的区别

特性接口抽象类
关键字interfaceabstract class
继承/实现数量类可实现多个接口类只能继承一个抽象类
实例字段不能有(只能有常量)可以有
构造方法不能有可以有
方法抽象方法 + default + static抽象方法 + 普通方法
主要用途能力契约、多角色、解耦「是一种」层次、模板、复用

提示

需要多继承能力纯行为契约、无状态时用接口;需要共同状态(字段)或部分已实现逻辑作为模板时用抽象类。很多 API 同时提供接口(如 List)和抽象类(如 AbstractList),接口对外契约,抽象类提供默认实现。


注意事项

  • 实现类必须实现接口中全部抽象方法:否则该类必须声明为 abstract
  • 实现方法必须为 public:接口方法默认为 public,实现类不能缩小为 package-private 或 private。
  • 多实现时方法签名冲突:若两个接口中有同名同参的 default 方法,实现类必须重写该方法并明确选择调用哪个接口的 default(如 InterfaceA.super.method()),否则编译报错。
  • 接口不能实例化:不能 new Drawable(),只能 new 实现类,再赋给接口引用。
  • 接口与多态:接口引用指向实现类对象时,调用的是实现类的方法,与「父类引用指向子类对象」的多态规则一致。

注意

实现接口时建议对每个实现方法使用 @Override 注解,便于编译器检查方法签名是否与接口一致,避免误写重载而非实现。


相关链接

基于 VitePress 构建