接口与抽象类

对比

对比项抽象类接口
关键字abstract classinterface
继承/实现extends,单继承implements,可实现多个
构造器
成员变量任意类型默认 public static final
普通方法有(可有实现)Java 8+ 支持 default/static
抽象方法abstract 修饰默认抽象(Java 8 前全部抽象)
访问修饰符无限制方法默认 public
适用场景is-a 关系,共享状态与实现can-do 关系,定义能力契约

抽象类

abstract 修饰,不能实例化,可以有抽象方法也可以全是具体方法。

public abstract class Shape {
    protected String color;
 
    public Shape(String color) {
        this.color = color;
    }
 
    // 抽象方法:子类必须实现
    public abstract double area();
 
    // 具体方法:子类可直接继承
    public void describe() {
        System.out.println("颜色: " + color + ", 面积: " + area());
    }
}
 
public class Circle extends Shape {
    private double radius;
 
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
 
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

使用场景:多个类有共同状态(字段)和部分共享逻辑,同时有不同的具体行为。

接口

public interface Flyable {
    // 常量(隐式 public static final)
    int MAX_HEIGHT = 10000;
 
    // 抽象方法(隐式 public abstract)
    void fly();
 
    // Java 8:default 方法(有默认实现,子类可选择重写)
    default void land() {
        System.out.println("正在降落");
    }
 
    // Java 8:static 方法
    static Flyable of(String type) {
        return () -> System.out.println(type + " is flying");
    }
 
    // Java 9:private 方法(供 default 方法复用,不对外暴露)
    private void logFlight(String msg) {
        System.out.println("[LOG] " + msg);
    }
}
 
// 实现多个接口
public class Eagle extends Bird implements Flyable, Huntable {
    @Override
    public void fly() { System.out.println("老鹰飞翔"); }
 
    @Override
    public void hunt() { System.out.println("老鹰捕猎"); }
}

接口默认方法冲突

一个类实现多个接口且都有同名 default 方法时,必须显式重写:

interface A {
    default void hello() { System.out.println("A"); }
}
 
interface B {
    default void hello() { System.out.println("B"); }
}
 
class C implements A, B {
    @Override
    public void hello() {
        A.super.hello(); // 显式选择调用 A 的实现
    }
}

函数式接口

只含一个抽象方法的接口,可用 @FunctionalInterface 标注,支持 Lambda 表达式。

@FunctionalInterface
public interface Converter<F, T> {
    T convert(F from);
}
 
Converter<String, Integer> toInt = Integer::parseInt;
System.out.println(toInt.convert("123")); // 123

JDK 内置常用函数式接口(java.util.function):

接口参数返回说明
Supplier<T>T提供值
Consumer<T>Tvoid消费值
Function<T,R>TR转换
Predicate<T>Tboolean判断
BiFunction<T,U,R>T, UR双参数转换
UnaryOperator<T>TT同类型转换

选择指南

需要共享字段状态?           → 抽象类
需要多继承能力?             → 接口
is-a 语义(狗是动物)?      → 抽象类
can-do 语义(鸟能飞)?      → 接口
定义回调 / 策略?            → 函数式接口

接口 vs 抽象类 演进

Java 8 之前接口只能有抽象方法,导致接口升级(新增方法)会破坏所有实现类。default 方法的引入解决了向后兼容问题,使接口能在不破坏现有实现的前提下扩展功能。


相关链接