一、抽象类(Abstract Class)
1. 核心概念
- 抽象类是用
abstract关键字修饰的类,不能被实例化,只能被继承。 - 可以包含抽象方法(没有方法体的方法)和具体方法。
- 作用:定义模板,强制子类实现抽象方法,实现代码复用。
2. 特点
- 若类包含至少一个抽象方法,则类必须声明为抽象类。
- 抽象类可以有构造方法(用于初始化子类对象)。
- 子类必须实现抽象类中的所有抽象方法(除非子类也是抽象类)。
3. 示例
java
复制
// 抽象类:动物
public abstract class Animal {
private String name;
// 抽象方法:子类必须实现
public abstract void makeSound();
// 具体方法:子类可直接使用或重写
public void sleep() {
System.out.println(name + "在睡觉");
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 子类继承抽象类
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(getName() + ":汪汪!");
}
}
// 使用抽象类
public class Main {
public static void main(String[] args) {
Animal dog = new Dog("旺财");
dog.makeSound(); // 输出:旺财:汪汪!
dog.sleep(); // 输出:旺财在睡觉
}
}
二、接口(Interface)
1. 核心概念
- 接口是使用
interface关键字定义的纯抽象类型,不能包含具体方法(Java 8+ 支持默认方法)。 - 类通过
implements关键字实现接口,一个类可以实现多个接口(支持多继承)。 - 作用:定义行为规范,实现解耦和多态。
2. 特点
- 接口中的方法默认是
public abstract,变量默认是public static final。 - Java 8 开始支持默认方法(
default方法)和静态方法。 - Java 9 开始支持私有方法。
3. 示例
java
复制
// 接口:飞行能力
public interface Flyable {
// 抽象方法
void fly();
// 默认方法(Java 8+)
default void land() {
System.out.println("降落");
}
// 静态方法(Java 8+)
static void showInfo() {
System.out.println("这是飞行能力接口");
}
}
// 实现接口的类
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟在飞翔");
}
}
// 使用接口
public class Main {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // 输出:鸟在飞翔
bird.land(); // 输出:降落(来自接口默认方法)
Flyable.showInfo(); // 输出:这是飞行能力接口
}
}
三、内部类(Inner Class)
1. 核心概念
- 内部类是定义在另一个类内部的类,可以访问外部类的所有成员(包括私有成员)。
- 分类:
- 静态内部类:用
static修饰,不依赖外部类实例。 - 非静态内部类:默认类型,依赖外部类实例。
- 匿名内部类:没有类名的内部类,通常用于实现接口或继承抽象类。
- 静态内部类:用
2. 静态内部类(Static Inner Class)
- 通过外部类名访问,只能访问外部类的静态成员。
- 示例:
java
复制
public class Outer {
private static String staticMsg = "外部类静态成员";
// 静态内部类
public static class StaticInner {
public void print() {
System.out.println(staticMsg); // 访问外部类静态成员
}
}
}
// 使用静态内部类
public class Main {
public static void main(String[] args) {
Outer.StaticInner inner = new Outer.StaticInner();
inner.print(); // 输出:外部类静态成员
}
}
3. 匿名内部类(Anonymous Inner Class)
- 没有类名的内部类,直接在代码中实现接口或继承抽象类。
- 适用场景:快速实现一次性使用的类。
- 示例:
java
复制
public interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
// 匿名内部类实现接口
Greeting greeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("你好,世界!");
}
};
greeting.sayHello(); // 输出:你好,世界!
}
}
四、抽象类 vs 接口
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 定义 | 用 abstract 修饰的类 |
用 interface 修饰的类型 |
| 方法实现 | 可以包含具体方法和抽象方法 | Java 8+ 支持默认方法和静态方法 |
| 多继承 | 单继承(一个类只能继承一个抽象类) | 多实现(一个类可实现多个接口) |
| 设计目的 | 提取类的共性(is-a关系) | 定义行为规范(can-do关系) |
| 构造方法 | 可以有构造方法 | 不能有构造方法 |
五、内部类总结
| 类型 | 特点 | 示例场景 |
|---|---|---|
| 静态内部类 | 不依赖外部类实例,只能访问外部类静态成员 | 工具类、Builder模式 |
| 非静态内部类 | 依赖外部类实例,可访问外部类所有成员 | 事件监听、数据封装 |
| 匿名内部类 | 没有类名,直接实现接口或继承抽象类 | 快速实现回调、临时逻辑 |
六、综合示例
java
复制
// 抽象类与接口结合使用
public abstract class Shape {
public abstract double area();
}
public interface Drawable {
void draw();
}
// 静态内部类实现接口
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
// 静态内部类实现Drawable接口
public static class Drawer implements Drawable {
private Circle circle;
public Drawer(Circle circle) {
this.circle = circle;
}
@Override
public void draw() {
System.out.println("绘制半径为" + circle.radius + "的圆");
}
}
}
// 匿名内部类实现接口
public class Main {
public static void main(String[] args) {
Circle circle = new Circle(5);
Drawable drawer = new Circle.Drawer(circle); // 静态内部类
drawer.draw(); // 输出:绘制半径为5的圆
// 匿名内部类直接实现Drawable
Drawable anonymousDrawer = new Drawable() {
@Override
public void draw() {
System.out.println("匿名内部类绘制操作");
}
};
anonymousDrawer.draw();
}
}
总结
- 抽象类:适合定义共性模板,强制子类实现特定行为。
- 接口:适合定义行为规范,支持多继承和解耦。
- 内部类:用于逻辑封装,静态内部类独立于外部类,匿名内部类简化代码。