应避免用接口定义常量,更禁用implements继承;正确做法是用final类封装极少数稳定通用值(如HTTP状态码),通过类名显式访问;动态配置必须外置到配置文件。

接口中定义常量本身不造成全局污染,但“让类实现该接口来使用常量”才会——这是污染的根源。规范做法不是限制怎么写接口,而是避免用接口承载常量;真要用,也必须守住边界:只放极少数跨模块稳定值,且绝不让业务类 implements 它。
只在接口里放真正通用、不可变的标识类常量
比如协议名、HTTP 状态码、固定路径前缀这类几乎永不变更、被多个无关模块引用的值:
- ✅ 合理:HttpConstants 中定义
String CONTENT_TYPE_JSON = "application/json"; - ✅ 合理:StatusCodes 中定义
int SERVICE_UNAVAILABLE = 503; - ❌ 避免:DatabaseConstants 中放
String DB_URL(应外置配置) - ❌ 避免:AppConstants 中塞满业务开关、超时时间、枚举别名(语义混杂、易变)
绝对不用 implements 继承常量
实现接口会让所有常量直接进入类的命名空间,导致:
- 调用时分不清是自己定义的字段还是继承来的(如
DEBUG_MODE和本地debugMode冲突) - IDE 无法准确跳转或重构,常量修改后所有实现类需重新编译
- 类的 public API 被悄悄扩大,破坏封装性
正确用法永远是显式通过接口名访问:HttpConstants.CONTENT_TYPE_JSON,而不是在类声明里写 implements HttpConstants。
立即学习“Java免费学习笔记(深入)”;
优先用 final 类替代接口存常量
更安全、更可控、语义更清晰:
- 定义一个不可实例化的类:
public final class HttpConstants { private HttpConstants() {} - 所有常量声明为
public static final,命名全大写下划线 - 天然杜绝被继承、被实现,也不会引发模块可见性问题(尤其 Java 9+ 模块系统下)
- 支持静态导入(
import static com.example.HttpConstants.*),兼顾简洁与可控
动态/可配常量必须移出代码
任何可能随环境变化的值——数据库地址、超时毫秒数、开关标志、消息模板——都不该出现在接口或类中:
- 放入
application.properties或config.yml - 用
@ConfigurationProperties或java.util.Properties加载 - 封装为不可变配置类,运行时注入,支持 profile 差异化


















