第 22 章:内部类与枚举
学习目标
- 掌握四种内部类的用法
- 理解枚举的本质和高级用法
一、为什么需要内部类?
内部类 = 定义在另一个类内部的类,用于逻辑分组和封装。
java
public class Outer {
private String outerField = "外部";
public class Inner { // ① 成员内部类
public void hello() {
System.out.println(outerField); // ✅ 直接访问外部类私有字段
}
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // ② 创建内部类需要外部实例
inner.hello();二、四种内部类
2.1 成员内部类
java
public class Outer {
private int x = 10;
public class Inner {
private int y = 20;
public void print() {
System.out.println("外部 x = " + x); // ① 访问外部类
System.out.println("内部 y = " + y);
}
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // ① 依赖外部实例
inner.print();2.2 静态内部类
java
public class Outer {
private static int x = 10; // ① 静态字段
public static class Inner { // ② 静态内部类
public void hello() {
System.out.println("静态 x = " + x); // ③ 只能访问静态成员
}
}
}
Outer.Inner inner = new Outer.Inner(); // ✅ 不需要外部实例
inner.hello();2.3 局部内部类
java
public class Outer {
public void method() {
int localVar = 10;
class LocalInner { // ① 定义在方法内
public void print() {
System.out.println(localVar); // ② 只能访问 effectively final
}
}
new LocalInner().print();
}
}2.4 匿名内部类(Lambda 的前身)
java
// 传统匿名内部类
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
// ✅ Lambda(JDK 8+,推荐)
Runnable r2 = () -> System.out.println("hello");三、枚举的本质
枚举是特殊的类,所有实例在编译时就确定:
java
public enum OrderStatus {
PENDING, // ① 枚举值(隐式 public static final)
PAID,
SHIPPED,
DELIVERED,
CANCELLED;
}java
OrderStatus status = OrderStatus.PAID;
System.out.println(status.name()); // "PAID"
System.out.println(status.ordinal()); // 1(顺序)
// 遍历所有枚举值
for (OrderStatus s : OrderStatus.values()) {
System.out.println(s);
}四、枚举的高级用法
4.1 枚举 + 字段 + 方法
java
public enum OrderStatus {
PENDING("待支付"),
PAID("已支付"),
SHIPPED("已发货"),
DELIVERED("已签收"),
CANCELLED("已取消");
private final String description; // ① 字段
OrderStatus(String description) { // ② 构造器(默认 private)
this.description = description;
}
public String getDescription() { // ③ 方法
return description;
}
public boolean canCancel() { // ④ 业务方法
return this == PENDING || this == PAID;
}
}4.2 枚举 + switch
java
public String handle(OrderStatus status) {
return switch (status) {
case PENDING -> "订单待支付";
case PAID -> "订单已支付";
case SHIPPED -> "订单已发货";
case DELIVERED -> "订单已签收";
case CANCELLED -> "订单已取消";
};
}4.3 枚举实现接口
java
public interface Describable {
String describe();
}
public enum OrderStatus implements Describable {
PENDING { // ① 每个枚举值可以独立实现
public String describe() {
return "待支付";
}
},
PAID {
public String describe() {
return "已支付";
}
};
}五、枚举 vs 常量类
java
// ❌ 常量类(不推荐)
public class OrderStatusConst {
public static final int PENDING = 1;
public static final int PAID = 2;
// 没有类型安全,没有命名空间
}
// ✅ 枚举(推荐)
public enum OrderStatus {
PENDING, PAID, SHIPPED;
// 类型安全 + 命名空间 + 内置方法
}六、本章小结
| 要点 | 关键 |
|---|---|
| 成员内部类 | 依赖外部实例 |
| 静态内部类 | 不依赖外部实例 |
| 局部内部类 | 在方法 / 块内 |
| 匿名内部类 | 一次性使用,Lambda 替代 |
| 枚举 | 有限个数的常量集,类型安全 |
| 枚举高级用法 | 字段、方法、switch、接口 |
动手练习
练习 1:基础题
定义枚举 Color(RED, GREEN, BLUE),给每个枚举添加 RGB 值字段。
练习 2:进阶题
定义枚举 Operation(PLUS, MINUS, MULTIPLY, DIVIDE),实现方法 apply(int a, int b) 计算结果。
下一章:第 23 章:Object 类 →