工具类必须私有化构造函数以防止实例化,标准写法为private DateUtils() { throw new UnsupportedOperationException("Utility class cannot be instantiated"); },配合public static方法和private static final字段;使用Lombok @UtilityClass可自动生成并强化约束。

Java 工具类(如 StringUtils、CollectionUtils)本质是静态方法集合,不应被 new 出实例。规范做法是将构造函数设为 private,彻底阻止外部创建对象,同时配合 static 方法提供纯功能调用。
为什么必须私有化构造函数
若不显式声明私有构造,编译器会默认提供一个公有无参构造——这意味着别人可以 new YourUtils(),哪怕类里全是静态方法,也会造成语义混乱和潜在误用。
- 防止意外实例化:避免对象状态污染或资源浪费
- 明确设计意图:告诉调用者“这个类只用来调用静态方法”
- 兼容 Lombok:若使用
@UtilityClass注解(Lombok 1.18.20+),它会自动添加私有构造 + final 修饰,无需手写
标准写法与常见变体
最简洁、最通用的写法是仅声明一个私有空构造,并抛出异常增强防御性:
public class DateUtils {
private DateUtils() {
throw new UnsupportedOperationException("Utility class cannot be instantiated");
}
public static String format(Date date) { ... }
}
- 不加
throws声明:构造函数本身不抛受检异常,UnsupportedOperationException是运行时异常,符合语义 - 不写任何逻辑:避免副作用;异常消息应清晰说明用途限制
- 不依赖注释解释:代码即文档,异常信息就是最直接的契约
搭配访问修饰符的协同作用
工具类自身通常用 public 保证可访问性,但内部成员需严格控制:
- 所有方法必须是
public static,确保可通过类名直接调用 - 所有字段必须是
private static final,杜绝实例变量和可变状态 - 避免
protected或包级访问:工具类不参与继承,也不应被同包其他类“绕过”静态约定去访问非静态成员
现代替代方案:Lombok @UtilityClass
如果你项目已引入 Lombok,推荐用 @UtilityClass 替代手写私有构造:
@UtilityClass
public class MathUtils {
public static int max(int a, int b) { return a > b ? a : b; }
}
- 自动生成
private构造、final类修饰、所有方法强制static - IDE 和编译器能识别该语义,对误用(如 new 实例)给出即时提示
- 比手写更少出错,也更贴近“工具类”的本意——零配置、零实例、纯函数式
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











