核心是用@nonnull拦截空参、@suppresswarnings("switch")强制覆盖枚举项、@deprecated管控生命周期、@documented统一契约。通过注解+ide检查+javadoc实现编译期约束与语义明确。

用内置注解约束枚举工厂的编写,核心不是给枚举加注解,而是用注解规范使用枚举的代码——特别是那些把枚举当参数、返回值或配置入口的工厂方法。Java本身没有专为“枚举工厂”设计的内置注解,但可以组合使用 @NonNull、@NotNull(来自JSR-305或Lombok)、@SuppressWarnings 和自定义校验逻辑,配合编译期检查与运行时防御,让团队写出语义清晰、无空指针、无非法值、不易漏分支的枚举工厂代码。
用 @NonNull + IDE/编译器拦截空枚举传参
枚举工厂方法若接收枚举参数(如 createHandler(OrderStatus status)),最常见问题是传入 null。JDK 8+ 的 java.util.Objects.requireNonNull 是运行时兜底,但更早拦截靠注解:
- 在参数上标注
@NonNull(需搭配支持 JSR-305 的编译器插件,如 Error Prone 或 IntelliJ 的 nullability 检查) - IDE 能实时标红
createHandler(null),Maven 编译时也可通过maven-compiler-plugin配合-Xlint:all提示潜在空值风险 - 避免只依赖
Objects.requireNonNull写在方法体第一行——它属于运行时防御,而注解驱动的静态检查才是团队协作的第一道防线
用 @SuppressWarnings("switch") 强制覆盖所有枚举项
工厂方法常以 switch 枚举分支返回不同实例(如按 PaymentMethod 返回对应处理器)。JDK 7+ 支持 switch 枚举,但新增枚举项后,旧 switch 容易遗漏 default 或新 case,导致逻辑静默失效。
- 不写
default:编译不报错,但新增枚举项后,该分支被跳过 → 必须显式列出所有 case - 写
default但只打日志:掩盖问题,难以定位漏处理场景 - 正确做法:删掉
default,改用@SuppressWarnings("switch")注解整个 switch 块,并确保 IDE(如 IntelliJ)开启 “Missing enum constant in switch” 检查 → 新增枚举项后,未覆盖的 case 会直接标黄警告
用 @Deprecated + @since 管控枚举项生命周期
枚举不是一成不变的。当某个枚举项(如 OrderStatus.CANCELLED_BY_USER)被业务弃用,但又不能立刻删除(因历史数据、序列化兼容),需让团队明确知道“不该再用”。
- 对废弃枚举常量加
@Deprecated,并配合@since "v2.3"注明弃用版本 - 在工厂方法中,对已废弃项的分支抛出
UnsupportedOperationException并附带提示:“此状态已停用,请改用 CANCELLED” - CI 流程中可加入 Checkstyle 规则,禁止在新代码中调用被
@Deprecated的枚举常量
用 @Documented + 标准 Javadoc 统一工厂契约
枚举工厂的本质是契约:输入什么枚举,输出什么行为,边界在哪。光靠代码无法传递完整语义,需注解+文档双驱动:
- 给工厂类或工厂方法加
@Documented,确保生成的 JavaDoc 包含注解说明 - Javadoc 中明确写清:
– 支持的枚举范围(是否包含所有values()?是否排除某些内部状态?)
– 返回对象的线程安全性
– 枚举值为 null 时的行为(抛 NPE?返回 null?)
– 是否缓存实例(如单例枚举工厂) - 配合
@apiNote(JDK 17+)或自定义@FactoryContract注解,把关键约束写进源码,而非藏在 Confluence 文档里










