MST

星途 面试题库

面试题:Java接口的默认方法与抽象类的区别及使用场景

详细说明Java 8引入接口默认方法后,接口的默认方法与抽象类的异同点,在设计一个新的功能模块时,如何选择使用接口默认方法还是抽象类,并给出具体理由。
20.9万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

相同点

  1. 提供通用实现:都可以为子类或实现类提供一些通用的代码实现,避免重复编写。例如,在处理一些基础的数据处理逻辑时,抽象类和接口默认方法都可以提供相应实现。
  2. 支持多态:子类或实现类都可以通过重写方法来实现不同的行为,实现多态性。比如一个绘图程序,不同图形类(继承抽象图形类或实现图形接口)通过重写绘制方法来实现各自的绘制逻辑。

不同点

  1. 定义方式
    • 抽象类:使用 abstract class 关键字定义,它可以包含抽象方法和具体方法,还能有成员变量、构造函数等。例如:
abstract class Shape {
    protected String color;
    public Shape(String color) {
        this.color = color;
    }
    public abstract void draw();
    public void printColor() {
        System.out.println("Color: " + color);
    }
}
- **接口**:使用 `interface` 关键字定义,Java 8 之前只能有抽象方法,Java 8 引入默认方法和静态方法后,接口可包含具体实现的方法,但接口中不能有成员变量(除了 `public static final` 类型),也没有构造函数。例如:
interface Drawable {
    void draw();
    default void setColor(String color) {
        System.out.println("Setting color in Drawable: " + color);
    }
}
  1. 继承关系
    • 抽象类:一个类只能继承一个抽象类,因为 Java 不支持多重继承。例如,Circle 类继承 Shape 抽象类:
class Circle extends Shape {
    private double radius;
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    @Override
    public void draw() {
        System.out.println("Drawing a circle with color " + color + " and radius " + radius);
    }
}
- **接口**:一个类可以实现多个接口,这使得类可以从多个来源获取行为。例如,`Rectangle` 类实现 `Drawable` 和 `Serializable` 接口:
class Rectangle implements Drawable, Serializable {
    private double width;
    private double height;
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle with width " + width + " and height " + height);
    }
}
  1. 访问修饰符
    • 抽象类:抽象类中的方法可以有各种访问修饰符,如 publicprotectedprivate 等。
    • 接口:接口中的方法默认是 publicabstract 的,默认方法默认是 public 的,不能使用其他访问修饰符(除了内部类)。

选择使用接口默认方法还是抽象类的理由

  1. 使用接口默认方法的场景
    • 需要多重实现:当一个类需要从多个不同来源获取行为时,使用接口。比如一个 SmartPhone 类既需要实现 Callable 接口用于打电话功能,又需要实现 Camera 接口用于拍照功能。
    • 对已有类添加新功能:如果要给一组不相关的类添加一个新的行为,接口默认方法是更好的选择。例如,要给多个不同类型的类添加一个通用的日志记录功能,不需要修改这些类的继承结构,只需让它们实现包含默认日志记录方法的接口即可。
  2. 使用抽象类的场景
    • 存在公共状态和行为:当一组相关的类有共同的状态(成员变量)和行为,并且这些类之间有明显的继承关系时,使用抽象类。例如,在一个游戏开发中,不同的角色类(战士、法师等)都继承自一个抽象的 Character 类,该抽象类包含生命值、攻击力等公共状态和一些公共行为方法。
    • 强制子类实现某些方法:如果希望强制子类实现某些方法,同时又提供一些默认实现,抽象类更合适。因为抽象类可以定义抽象方法,要求子类必须实现,同时也能提供具体方法的默认实现。