在 Java 中,接口和抽象类是两种用于定义类行为的抽象概念,对于初学者来说很容易将两者搞混,所以接下来我会具体阐述接口与抽象类定义与区别。
接口 (Interface)
-
定义:
- 接口是一个完全抽象的类,它只能包含抽象方法(除非使用
default
或static
方法)。 - 接口中不能有实例变量,但可以包含常量(
public static final
)。
- 接口是一个完全抽象的类,它只能包含抽象方法(除非使用
-
方法:
- 接口中的方法默认是
public
和abstract
的,即使没有显式声明。 - 从 Java 8 开始,接口可以包含
default
方法和static
方法。 - 从 Java 9 开始,接口可以包含
private
方法。
- 接口中的方法默认是
-
实现:
- 一个类可以实现多个接口,用逗号分隔。
- 必须实现接口中的所有抽象方法。
-
继承:
- 接口可以继承多个接口,但不能继承类。
-
实例化:
- 接口不能被实例化。
抽象类 (Abstract Class)
-
定义:
- 抽象类是一种不能实例化的类,主要用于作为其他类的基类。
- 可以包含抽象方法和具体方法。
- 可以包含实例变量。
-
方法:
- 抽象方法没有方法体,需要子类实现。
- 抽象类可以包含具体方法(有方法体)。
-
实现:
- 一个类只能继承一个抽象类(Java 中不支持多继承)。
- 子类必须实现所有抽象方法,除非子类也是抽象类。
-
继承:
- 抽象类可以继承其他类和接口。
-
实例化:
- 抽象类不能被实例化。
具体比较
特性 | 接口 (Interface) | 抽象类 (Abstract Class) |
---|---|---|
默认修饰符 | 方法:public 和 abstract ,变量:public static final | 方法和变量:可以有任何访问修饰符 |
方法实现 | 只能包含抽象方法(Java 8+ 可以有 default 和 static 方法) | 可以包含抽象方法和具体方法 |
变量 | 只能包含常量 | 可以包含实例变量 |
继承 | 可以继承多个接口 | 只能继承一个类 |
实现 | 一个类可以实现多个接口 | 一个类只能继承一个抽象类 |
实例化 | 不能实例化 | 不能实例化 |
使用场景
-
接口:
- 适用于定义一组不相关类的共同行为。
- 用于实现多重继承。
- 常用于定义与外部系统的契约(如回调接口、事件处理接口等)。
-
抽象类:
- 适用于定义一组相关类的共同行为和状态。
- 用于共享代码(方法实现、实例变量)给子类。
- 适用于类层次结构中的基类。
接下来我们以动物类举例 :
接口:
interface Animal {
void eat();
void sleep();
}
interface Pet {
void play();
}
class Dog implements Animal, Pet {
@Override
public void eat() {
System.out.println("Dog is eating");
}
@Override
public void sleep() {
System.out.println("Dog is sleeping");
}
@Override
public void play() {
System.out.println("Dog is playing");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.sleep();
dog.play();
}
}
抽象类:
abstract class Animal {
// 实例变量
String name;
// 构造方法
public Animal(String name) {
this.name = name;
}
// 抽象方法
abstract void eat();
// 具体方法
void sleep() {
System.out.println(name + " is sleeping");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
void eat() {
System.out.println(name + " is eating");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.eat();
dog.sleep();
}
}
- 接口:用于定义类的行为契约,支持多继承,不能包含实例变量,方法默认是抽象的。
- 抽象类:用于定义类的共同行为和状态,只能单继承,可以包含实例变量和具体方法
总结:
由此可见,
接口(Interface)能够定义抽象方法,支持多继承,但不能包含实例变量
抽象类(Abstract Class)只能单继承,且可以包含具体方法和实例变量