通过私有构造器强化不可实例化的能力
在面向对象编程中,有时我们需要创建一些只包含静态方法和静态字段的工具类(Utility Class),这些类不应该被实例化。
有些类只是作为静态方法和静态字段的容器,它们不需要也不应该被实例化。
比如:
- 数学工具类(MathUtils)
- 字符串处理工具类(StringUtils)
- 常量定义类(Constants)
- 日志工具类(Logger)
-
在没有显示的编写构造类时,编译器就会提供一个共有、无参的缺省构造器(默认)。于用户而言,这个构造器与其他的构造器没有任何区别。可能会被无意识地实例化。
-
企图通过将类做成抽象类来强制该类不可被实例化是行不通的,该类可以子类化并且被实例化,会误导用户是专门为了继承而设计。
由于只有当类不包含显式的构造器时,编译器才会生成缺省的构造器,因此只要让这个类包含一个私有构造器就可以。
// 不可实例化的工具类
public class StringUtils {
// 私有构造器
private StringUtils() {
throw new AssertionError("Cannot be instantiated");
}
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
}
// 尝试继承 - 这会编译错误!
public class ExtendedStringUtils extends StringUtils { // 编译错误
// 子类构造器必须调用父类构造器(显式或隐式)
// 但父类只有私有构造器,无法访问
}
ssertiongrror不是必需的,但是它可以避免不小心在类的内部调用构造器。它保证该类在任何情况下都不会被实例化。这种习惯用法有点违背直觉,好像构造器就是专门设计成不能被调用一样。因此,明智的做法就是在代码中增加一条注释。
不过这样就此类就没办法子类化了。子类构造器必须调用父类构造器(显式或隐式),但父类只有私有构造器,无法访问。
1009

被折叠的 条评论
为什么被折叠?



