MST

星途 面试题库

面试题:Java中抽象类与接口在定义和使用上的区别

请详细阐述Java抽象类和接口在定义方式、成员变量、成员方法、继承与实现关系等方面的主要区别,并举例说明在何种场景下会优先选择使用抽象类或接口。
21.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

定义方式

  • 抽象类:使用 abstract 关键字修饰,定义格式为 abstract class 类名 {... }
  • 接口:使用 interface 关键字修饰,定义格式为 interface 接口名 {... }

成员变量

  • 抽象类:可以有各种访问修饰符(privateprotectedpublic 等)的成员变量,也可以有 final 修饰的常量。例如:
abstract class AbstractClass {
    private int privateVar;
    protected String protectedVar;
    public static final double PI = 3.14159;
}
  • 接口:成员变量默认都是 public static final 类型的常量,必须在声明时初始化。例如:
interface MyInterface {
    int DEFAULT_VALUE = 10;
}

成员方法

  • 抽象类:可以有抽象方法(只有声明,没有实现,用 abstract 修饰)和具体方法(有方法体)。例如:
abstract class AbstractClass {
    public abstract void abstractMethod();
    public void concreteMethod() {
        System.out.println("This is a concrete method.");
    }
}
  • 接口:JDK 8 之前,接口中的方法默认都是抽象的,且只能是 public abstract,方法不能有方法体;JDK 8 开始可以有默认方法(用 default 修饰,有方法体)和静态方法(用 static 修饰,有方法体)。例如:
interface MyInterface {
    void abstractMethod();
    default void defaultMethod() {
        System.out.println("This is a default method.");
    }
    static void staticMethod() {
        System.out.println("This is a static method.");
    }
}

继承与实现关系

  • 抽象类:一个类只能继承一个抽象类,通过 extends 关键字实现继承。例如:
class SubClass extends AbstractClass {
    @Override
    public void abstractMethod() {
        System.out.println("Implementation of abstract method.");
    }
}
  • 接口:一个类可以实现多个接口,通过 implements 关键字实现。例如:
class ImplementingClass implements MyInterface {
    @Override
    public void abstractMethod() {
        System.out.println("Implementation of interface method.");
    }
}

场景选择

  • 优先选择抽象类的场景
    • 当存在一组相关的类,它们有一些共同的属性和行为,且这些行为中有部分需要具体实现,部分需要子类去定制时,使用抽象类。例如,在图形绘制系统中,Shape 抽象类可以有 color 成员变量和 draw 抽象方法,CircleRectangle 等子类继承 Shape 并实现 draw 方法。
abstract class Shape {
    private String color;
    public Shape(String color) {
        this.color = color;
    }
    public abstract void draw();
}

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 " + getColor() + " circle with radius " + radius);
    }
    private String getColor() {
        return color;
    }
}
  • 优先选择接口的场景
    • 当需要实现某种功能,而这个功能与类的继承体系无关,或者希望一个类能同时具备多种功能时,使用接口。例如,在电商系统中,Payable 接口可以定义支付相关的方法,Product 类和 Service 类都可以实现 Payable 接口来支持支付功能。
interface Payable {
    void pay();
}

class Product implements Payable {
    @Override
    public void pay() {
        System.out.println("Paying for the product.");
    }
}

class Service implements Payable {
    @Override
    public void pay() {
        System.out.println("Paying for the service.");
    }
}