第33章

Java接口(Interface)

掌握接口的定义、实现和多重继承的强大特性

学习目标

接口概述

接口(Interface)是Java中一种重要的引用数据类型,它定义了类必须实现的方法契约。接口提供了一种实现多重继承的方式,是面向对象编程中实现抽象和多态的重要工具。

什么是接口?
接口是一个完全抽象的类,它只包含常量和抽象方法的声明。从Java 8开始,接口还可以包含默认方法和静态方法。接口定义了类应该做什么,但不规定如何做。

契约定义

基本语法:
public interface InterfaceName {
    // 常量(默认public static final)
    int CONSTANT = 100;
    
    // 抽象方法(默认public abstract)
    void method1();
    String method2(int param);
}
  • 定义方法签名
  • 声明常量
  • 建立规范契约
  • 支持多重继承

接口实现

实现语法:
public class MyClass implements InterfaceName {
    @Override
    public void method1() {
        // 实现方法
    }
    
    @Override
    public String method2(int param) {
        return "result";
    }
}
  • 使用implements关键字
  • 必须实现所有抽象方法
  • 可以实现多个接口
  • 支持方法重写

多重继承

多接口实现:
public class MultiImpl 
    implements Interface1, Interface2, Interface3 {
    
    // 实现所有接口的方法
    @Override
    public void method1() { }
    
    @Override
    public void method2() { }
    
    @Override
    public void method3() { }
}
  • 实现多个接口
  • 解决单继承限制
  • 组合不同功能
  • 提高代码灵活性

Java 8新特性

默认方法和静态方法:
public interface ModernInterface {
    // 默认方法
    default void defaultMethod() {
        System.out.println("默认实现");
    }
    
    // 静态方法
    static void staticMethod() {
        System.out.println("静态方法");
    }
}
  • 默认方法实现
  • 静态方法支持
  • 向后兼容性
  • 接口演进能力

接口定义详解

接口声明语法

完整的接口定义示例:
/**
 * 可绘制接口 - 定义图形绘制的基本契约
 */
public interface Drawable {
    // 常量(隐式public static final)
    String DEFAULT_COLOR = "BLACK";
    int MAX_SIZE = 1000;
    
    // 抽象方法(隐式public abstract)
    void draw();
    void setColor(String color);
    void resize(int width, int height);
    
    // 默认方法(Java 8+)
    default void show() {
        System.out.println("显示图形");
        draw();
    }
    
    // 静态方法(Java 8+)
    static void printInfo() {
        System.out.println("这是一个可绘制接口");
    }
}
接口成员的默认修饰符:
• 所有变量都是 public static final(常量)
• 所有抽象方法都是 public abstract
• 默认方法必须用 default 关键字
• 静态方法必须用 static 关键字

接口实现

实现Drawable接口:
/**
 * 圆形类 - 实现Drawable接口
 */
public class Circle implements Drawable {
    private String color;
    private int radius;
    
    public Circle(int radius) {
        this.radius = radius;
        this.color = DEFAULT_COLOR; // 使用接口常量
    }
    
    @Override
    public void draw() {
        System.out.println("绘制半径为 " + radius + " 的 " + color + " 圆形");
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public void resize(int width, int height) {
        // 对于圆形,使用较小的值作为半径
        this.radius = Math.min(width, height) / 2;
    }
    
    // 可以重写默认方法
    @Override
    public void show() {
        System.out.println("=== 圆形信息 ===");
        Drawable.super.show(); // 调用接口的默认实现
        System.out.println("半径: " + radius);
    }
}

多重继承

Java类只能继承一个父类,但可以实现多个接口,这就是接口实现多重继承的方式。

多接口实现示例:
// 可移动接口
interface Movable {
    void move(int x, int y);
    default void stop() {
        System.out.println("停止移动");
    }
}

// 可旋转接口
interface Rotatable {
    void rotate(double angle);
    default void resetRotation() {
        rotate(0);
    }
}

// 可缩放接口
interface Scalable {
    void scale(double factor);
}

/**
 * 图形类 - 实现多个接口
 */
public class Shape implements Drawable, Movable, Rotatable, Scalable {
    private int x, y;
    private double rotation;
    private double scale;
    private String color;
    
    public Shape() {
        this.x = 0;
        this.y = 0;
        this.rotation = 0;
        this.scale = 1.0;
        this.color = Drawable.DEFAULT_COLOR;
    }
    
    // 实现Drawable接口
    @Override
    public void draw() {
        System.out.println("在位置(" + x + ", " + y + ")绘制" + color + "图形");
        System.out.println("旋转角度: " + rotation + "°, 缩放比例: " + scale);
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
    
    @Override
    public void resize(int width, int height) {
        // 根据尺寸调整缩放比例
        this.scale = Math.min(width, height) / 100.0;
    }
    
    // 实现Movable接口
    @Override
    public void move(int x, int y) {
        this.x = x;
        this.y = y;
        System.out.println("移动到位置: (" + x + ", " + y + ")");
    }
    
    // 实现Rotatable接口
    @Override
    public void rotate(double angle) {
        this.rotation = angle;
        System.out.println("旋转到角度: " + angle + "°");
    }
    
    // 实现Scalable接口
    @Override
    public void scale(double factor) {
        this.scale = factor;
        System.out.println("缩放比例设置为: " + factor);
    }
}
多重继承的优势:
• 组合多种功能和特性
• 提高代码的灵活性和可扩展性
• 实现更细粒度的功能划分
• 支持更好的代码复用

接口与抽象类对比

特性 接口(Interface) 抽象类(Abstract Class)
关键字 interface abstract class
继承方式 implements(可多个) extends(只能一个)
方法实现 抽象方法 + 默认方法 + 静态方法 抽象方法 + 具体方法
变量类型 只能是常量(public static final) 可以有实例变量和常量
构造方法 不能有构造方法 可以有构造方法
访问修饰符 方法默认public 可以有各种访问修饰符
使用场景 定义规范、实现多重继承 代码复用、部分实现
选择建议:
// 使用接口的场景
interface PaymentProcessor {
    void processPayment(double amount);
    default void logTransaction() {
        System.out.println("记录交易日志");
    }
}

// 使用抽象类的场景
abstract class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    // 具体方法
    public void sleep() {
        System.out.println(name + " 正在睡觉");
    }
    
    // 抽象方法
    public abstract void makeSound();
}

接口的高级特性

默认方法

Java 8引入了默认方法,允许在接口中提供方法的默认实现,这样可以在不破坏现有实现的情况下向接口添加新方法。

默认方法示例:
interface Collection {
    void add(Object item);
    void remove(Object item);
    int size();
    
    // 默认方法
    default boolean isEmpty() {
        return size() == 0;
    }
    
    default void clear() {
        // 默认的清空实现
        while (!isEmpty()) {
            // 需要子类提供具体的移除逻辑
        }
    }
    
    // 可以调用其他默认方法
    default void printInfo() {
        System.out.println("集合大小: " + size());
        System.out.println("是否为空: " + isEmpty());
    }
}

静态方法

接口中的静态方法属于接口本身,可以直接通过接口名调用,不能被实现类重写。

静态方法示例:
interface MathUtils {
    // 静态方法
    static double calculateArea(double radius) {
        return Math.PI * radius * radius;
    }
    
    static double calculatePerimeter(double radius) {
        return 2 * Math.PI * radius;
    }
    
    static void printFormula() {
        System.out.println("圆面积公式: π × r²");
        System.out.println("圆周长公式: 2 × π × r");
    }
}

// 使用静态方法
public class GeometryCalculator {
    public static void main(String[] args) {
        double radius = 5.0;
        
        // 直接通过接口名调用静态方法
        double area = MathUtils.calculateArea(radius);
        double perimeter = MathUtils.calculatePerimeter(radius);
        
        System.out.println("半径: " + radius);
        System.out.println("面积: " + area);
        System.out.println("周长: " + perimeter);
        
        MathUtils.printFormula();
    }
}

接口继承

接口可以继承其他接口,支持多重继承,形成接口的层次结构。

接口继承示例:
// 基础接口
interface Readable {
    String read();
}

interface Writable {
    void write(String data);
}

// 继承多个接口
interface ReadWritable extends Readable, Writable {
    // 可以添加新方法
    void copy();
    
    // 默认实现
    default void backup() {
        String data = read();
        write("backup_" + data);
    }
}

// 实现继承的接口
public class File implements ReadWritable {
    private String content;
    
    @Override
    public String read() {
        return content;
    }
    
    @Override
    public void write(String data) {
        this.content = data;
    }
    
    @Override
    public void copy() {
        String data = read();
        write(data + "_copy");
    }
}

实战案例

💻 查看完整代码 - 在线IDE体验

通过一个完整的图形绘制系统案例,展示接口在实际项目中的应用。

接口设计最佳实践

接口设计原则

推荐做法

  • 单一职责:每个接口应该有明确的单一职责
  • 命名规范:使用形容词或能力描述(如Readable、Drawable)
  • 方法简洁:接口方法应该简洁明了
  • 文档完善:为接口和方法提供清晰的文档
  • 向后兼容:使用默认方法保持向后兼容性

避免做法

  • 过度设计:避免创建过于复杂的接口层次
  • 方法过多:单个接口不要包含太多方法
  • 实现依赖:接口不应该依赖具体实现
  • 常量滥用:避免在接口中定义过多常量
  • 标记接口:谨慎使用空接口作为标记

章节总结