enum定义业务常量天然线程安全,关键在避免可变状态:字段用final、不持可变集合、用map.ofentries构建不可变映射;行为逻辑优先抽象方法实现;集成spring时禁用@autowired。

用 enum 定义业务常量,天然具备类型安全、不可变、单例、可枚举等优势;只要不暴露可变状态或共享可变对象,它本身就是线程安全的。关键在于设计时避免“藏坑”,而非额外加锁。
用 enum 封装不可变的业务标识值
把字符串/数字常量收拢到 enum 中,既防拼写错误,又便于 IDE 提示和类型推导。
public enum OrderStatus {
CREATED("created", 10),
PAID("paid", 20),
SHIPPED("shipped", 30),
COMPLETED("completed", 40);
private final String code;
private final int sort;
OrderStatus(String code, int sort) {
this.code = code; // final 字段,构造即冻结
this.sort = sort;
}
public String getCode() { return code; }
public int getSort() { return sort; }
}
- 每个枚举实例在类加载时初始化,且仅初始化一次,JVM 保证其线程安全
- 字段声明为
final,杜绝运行时修改 - 不提供 setter、不持有可变集合(如
ArrayList)、不缓存外部可变对象(如未包装的HashMap)
避免在 enum 中持有可变状态
常见反模式:在 enum 里缓存非线程安全的 Map 或懒加载可变对象。
- ❌ 错误:直接用
new HashMap()作为 enum 字段 —— 多线程并发 put 可能导致死循环或数据错乱 - ✅ 正确:用
Map.copyOf(...)、UnmodifiableMap或ConcurrentHashMap显式封装 - ✅ 更推荐:用静态块 +
Map.ofEntries()构建不可变映射,零运行时开销
public enum PaymentMethod {
ALIPAY("alipay", "支付宝"),
WECHAT("wechat", "微信支付");
private final String code;
private final String desc;
PaymentMethod(String code, String desc) {
this.code = code;
this.desc = desc;
}
// 静态不可变映射,线程安全且高效
private static final Map<string paymentmethod> BY_CODE =
Map.ofEntries(
Map.entry("alipay", ALIPAY),
Map.entry("wechat", WECHAT)
);
public static PaymentMethod fromCode(String code) {
return BY_CODE.get(code); // null-safe if needed
}
}</string>
需要行为逻辑?用抽象方法 + 具体实现
当不同常量需执行不同逻辑(如状态流转校验),优先用 enum 的抽象方法,而非 if-else 分支。
- 每个枚举值自行实现方法,逻辑内聚,扩展新增状态只需加一个 enum 实例
- 方法体中只访问自身 final 字段或调用纯函数,不操作共享可变资源
- 若需调用外部服务,确保该服务本身线程安全,enum 不承担同步职责
public enum DiscountType {
FIXED_AMOUNT {
@Override
public BigDecimal apply(BigDecimal origin, BigDecimal param) {
return origin.subtract(param); // 参数是 final,无副作用
}
},
PERCENTAGE {
@Override
public BigDecimal apply(BigDecimal origin, BigDecimal rate) {
return origin.multiply(rate).divide(new BigDecimal("100"));
}
};
public abstract BigDecimal apply(BigDecimal origin, BigDecimal param);
}
与 Spring 等框架集成时保持简洁
Spring 可自动绑定 enum(如 @RequestParam、@Value),无需额外配置;但注意:
- 确保 enum 的
toString()或name()符合传输约定,必要时重写toString()返回 code - 避免在 enum 中注入
@AutowiredBean —— 枚举类由 JVM 加载,早于 Spring 容器,会导致空指针 - 若需动态能力(如从 DB 加载),应将逻辑移出 enum,用独立 service 管理,enum 仅作类型锚点











