Bootstrap

Java 中 interface 和 abstract 之间的区别

在Java中,interface 和 abstract class 是两种用于实现抽象和多态的机制,它们的主要的区别如下:


1. 定义与用途

  • 抽象类 (Abstract Class):

    • 用 abstract 关键字定义。

    • 可以包含抽象方法(没有实现的方法)和具体方法(有实现的方法)。

    • 用于表示一种“是”关系,即子类是父类的一种特殊类型。

    • 适合用于有部分共同实现但需要进一步扩展的类。

  • 接口 (Interface):

    • 用 interface 关键字定义。

    • 只能包含抽象方法(Java 8 之前),默认方法(default 方法)和静态方法(Java 8 及以后)。

    • 用于表示一种“能做”关系,即类可以实现多个接口,表明它具有多种能力。

    • 适合用于定义行为契约,允许多个类实现相同的接口。

2. 方法实现

  • 抽象类:

    • 可以包含抽象方法和具体方法。

    • 抽象方法必须由子类实现。

    • 具体方法可以直接在抽象类中实现,子类可以选择重写。

  • 接口:

    • Java 8 之前只能包含抽象方法。

    • Java 8 引入了默认方法(default 方法)和静态方法,允许在接口中提供方法实现。

    • 默认方法可以在接口中提供默认实现,子类可以选择重写。

    • 静态方法可以直接通过接口调用。

3. 多继承

  • 抽象类:

    • Java 不支持多继承,一个类只能继承一个抽象类。

    • 子类只能继承一个抽象类。

  • 接口:

    • 一个类可以实现多个接口。

    • 接口支持多继承,即一个接口可以继承多个接口。

4. 成员变量

  • 抽象类:

    • 可以包含成员变量,可以是任意访问修饰符(publicprotectedprivate)。

    • 成员变量可以是静态或非静态的。

  • 接口:

    • 只能包含常量(public static final),即接口中的变量默认是常量。

    • 不能有非静态的成员变量。

5. 构造器

  • 抽象类:

    • 可以有构造器,用于初始化抽象类的状态。

    • 构造器在子类实例化时被调用。

  • 接口:

    • 不能有构造器,因为接口不能被实例化。

6. 访问修饰符

  • 抽象类:

    • 方法可以有任意访问修饰符(publicprotectedprivate)。

    • 抽象方法必须是 public 或 protected,因为子类需要实现它们。

  • 接口:

    • 方法默认是 public,不能使用 private 或 protected

    • 默认方法和静态方法可以有 public 或 private 访问修饰符(Java 9 及以后)。

7. 使用场景

  • 抽象类:

    • 当多个类有共同的代码逻辑时,可以使用抽象类来提取这些共同逻辑。

    • 当需要定义一些子类必须实现的抽象方法时。

  • 接口:

    • 当需要定义一组方法规范,而不关心具体实现时。

    • 当需要实现多继承时,因为一个类可以实现多个接口。


示例代码 


// 抽象类
abstract class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    // 抽象方法
    public abstract void makeSound();

    // 具体方法
    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

// 接口
interface Flyable {
    void fly();
}

// 实现抽象类和接口
class Bird extends Animal implements Flyable {
    public Bird(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " is chirping.");
    }

    @Override
    public void fly() {
        System.out.println(name + " is flying.");
    }
}

public class Main {
    public static void main(String[] args) {
        Bird bird = new Bird("Sparrow");
        bird.makeSound(); // Sparrow is chirping.
        bird.fly();      // Sparrow is flying.
        bird.sleep();     // Sparrow is sleeping.
    }
}

总结

  • 抽象类 更适合用于有部分共同实现的类层次结构。

  • 接口 更适合用于定义行为契约,允许多个类实现相同的接口。

根据具体需求选择合适的机制,或者结合使用两者。

;