MST

星途 面试题库

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

请详细阐述Java中接口与抽象类在定义方式(成员变量、方法等方面)以及使用场景上存在哪些主要区别。
33.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

定义方式区别

  1. 成员变量
    • 抽象类:可以拥有各种访问修饰符(private、default、protected、public)的成员变量,既可以是常量,也可以是变量。例如:
abstract class AbstractClass {
    private int privateVar;
    protected final String CONSTANT = "常量";
    public int publicVar;
}
  • 接口:成员变量默认是public static final修饰的,即只能是常量。例如:
interface MyInterface {
    int VALUE = 10; // 实际等同于public static final int VALUE = 10;
}
  1. 方法
    • 抽象类:可以包含抽象方法和具体方法。抽象方法只有声明,没有实现;具体方法有方法体。例如:
abstract class AbstractClass {
    // 抽象方法
    public abstract void abstractMethod();
    // 具体方法
    public void concreteMethod() {
        System.out.println("这是一个具体方法");
    }
}
  • 接口:在Java 8之前,接口中的方法全部是抽象的(默认public abstract修饰),没有方法体。从Java 8开始,接口可以有默认方法(使用default关键字修饰,有方法体)和静态方法(使用static关键字修饰,有方法体)。例如:
interface MyInterface {
    void abstractMethod(); // 实际等同于public abstract void abstractMethod();
    default void defaultMethod() {
        System.out.println("这是一个默认方法");
    }
    static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
}
  1. 构造函数
    • 抽象类:可以有构造函数,虽然不能直接实例化,但构造函数可用于为子类提供初始化逻辑。例如:
abstract class AbstractClass {
    private int value;
    AbstractClass(int value) {
        this.value = value;
    }
}
  • 接口:不能有构造函数,因为接口不是用来实例化的,而是被类实现。

使用场景区别

  1. 抽象类
    • 场景一:提取公共代码:当多个类有一些共同的属性和方法实现时,可以将这些共性提取到抽象类中。例如,Animal抽象类包含name属性和eat()具体方法,DogCat类继承自Animal类,这样可以复用代码。
abstract class Animal {
    protected String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat() {
        System.out.println(name + "正在吃东西");
    }
    public abstract void makeSound();
}
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}
  • 场景二:定义不完整的行为:如果某些行为在抽象类中无法完全确定具体实现,可将其定义为抽象方法,由子类去实现。如上述Animal类中的makeSound()方法。
  1. 接口
    • 场景一:实现多态和功能扩展:当一个类需要实现多个不同类型的行为时,可通过实现多个接口来达成。例如,一个Car类既可以实现Driveable接口表示可驾驶,又可以实现Serializable接口表示可序列化。
interface Driveable {
    void drive();
}
interface Serializable {
    // 接口中通常定义方法签名,这里省略具体方法
}
class Car implements Driveable, Serializable {
    @Override
    public void drive() {
        System.out.println("汽车在行驶");
    }
}
  • 场景二:定义规范和契约:接口定义了一组方法的签名,实现接口的类必须按照接口定义的规范来实现这些方法。例如,在一个电商系统中,Payment接口定义了支付相关的方法,AlipayPaymentWechatPayment类实现该接口,保证了支付功能的一致性和规范性。
interface Payment {
    void pay(double amount);
}
class AlipayPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("使用支付宝支付" + amount + "元");
    }
}
class WechatPayment implements Payment {
    @Override
    public void pay(double amount) {
        System.out.println("使用微信支付" + amount + "元");
    }
}