特性 | 抽象类(abstract class) | 接口(interface) |
---|---|---|
实例化 | 不能被实例化 | 不能被实例化 |
定义类型引用 | 可以定义抽象类类型的引用 | 可以定义接口类型的引用 |
方法实现要求 | 子类需要实现所有抽象方法,否则仍需声明为抽象类 | 实现类需要实现所有方法 |
构造器 | 可以定义构造器 | 不能定义构造器 |
方法类型 | 可以包含抽象方法和具体方法 | 只能包含抽象方法(在Java 8及以后可以有默认方法和静态方法) |
成员访问修饰符 | 可以是private、默认、protected、public | 只能是public(包括成员变量和方法) |
成员变量 | 可以定义成员变量 | 定义的成员变量实际上是常量(隐式地为public static final) |
与抽象方法的关系 | 有抽象方法的类必须被声明为抽象类,但抽象类未必有抽象方法 | 接口中的所有方法默认是抽象方法(Java 8及以后可以有默认实现) |
继承/实现 | 使用extends 关键字继承 | 使用implements 关键字实现 |
多重继承/实现 | 单继承,但可以实现多个接口 | 一个类可以实现多个接口 |
用途 | 用于表示一种继承关系,强调”是一种(is-a)"的关系 | 用于表示一种实现关系,强调“具有(has-a)"或者"能做(can-do)"的关系 |
状态(成员变量)与行为 | 可以包含状态(成员变量)和行为(方法) | 主要关注行为(方法),不包含状态(成员变量) |
设计理念 | 用于对类的抽象,表示一种基类 | 用于定义一组方法的集合,表示一种能力或者契约 |
简单示例
抽象类
abstract class Animal {
// 成员变量
private String name;
// 构造器
public Animal(String name) {
this.name = name;
}
// 抽象方法
public abstract void makeSound();
// 具体方法
public void eat() {
System.out.println(name + " is eating.");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println("Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.makeSound(); // Woof!
dog.eat(); // Buddy is eating.
}
}
接口示例
interface Swimmable {
// 抽象方法
void swim();
// Java 8及以后的默认方法
default void dive() {
System.out.println("Diving...");
}
// 静态方法
static void describeSwimming() {
System.out.println("Swimming is a form of locomotion.");
}
}
class Fish implements Swimmable {
@Override
public void swim() {
System.out.println("Fish is swimming.");
}
}
public class Main {
public static void main(String[] args) {
Fish fish = new Fish();
fish.swim(); // Fish is swimming.
fish.dive(); // Diving...
Swimmable.describeSwimming(); // Swimming is a form of locomotion.
}
}
结语
-
实例化:
- 抽象类和接口都不能被实例化,但可以通过它们的子类或实现类来创建对象。
-
构造器:
- 抽象类可以定义构造器,用于初始化抽象类的成员变量。子类在继承抽象类时,会调用抽象类的构造器。
- 接口不能定义构造器,因为它不包含任何实例字段。
-
方法:
- 抽象类可以包含抽象方法和具体方法。抽象方法必须由子类实现,而具体方法可以直接在抽象类中实现。
- 接口在Java 8之前只能包含抽象方法。Java 8及以后,接口可以包含默认方法和静态方法。默认方法是非抽象的方法,可以在接口中实现;静态方法是接口级别的方法,不能通过接口实例调用。
-
成员访问修饰符:
- 抽象类的成员可以是private、默认、protected、public,这允许抽象类有更多的封装性和灵活性。
- 接口的成员(包括方法和变量)默认是public的,这意味着它们对所有实现类都是可见的。
-
成员变量:
- 抽象类可以定义成员变量,这些变量可以是实例变量或静态变量。
- 接口中定义的成员变量实际上是常量,它们默认是public static final的,这意味着它们的值在编译时就已经确定,并且不能被修改。
-
继承/实现:
- 一个类只能继承一个抽象类(单继承),但可以实现多个接口(多实现)。
- 这使得接口在需要多重继承的场景中更加有用,因为它允许类实现多个接口来获取不同的能力或契约。
-
设计理念:
- 抽象类主要用于类的抽象,表示一种基类或通用类型。它允许子类共享一些通用的实现和状态。
- 接口主要用于定义方法的集合,表示一种能力或契约。它允许不同的类实现相同的方法集合,从而实现多态性和模块化设计。