我有一个充满实用功能的类。实例化它的实例没有语义意义,但我仍然想调用它的方法。处理这个问题的最佳方法是什么?静态类?抽象的?
8 回答
标记为 final 的类上的私有构造函数和静态方法。
根据伟大的书“Effective Java”:
第 4 条:使用私有构造函数强制执行不可实例化
- 试图通过使类抽象来强制执行不可实例化是行不通的。
- 仅当类不包含显式构造函数时才会生成默认构造函数,因此可以通过包含私有构造函数使类不可实例化:
// Noninstantiable utility class
public class UtilityClass
{
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
}
因为显式构造函数是私有的,所以在类之外是不可访问的。AssertionError 不是严格要求的,但它提供了保险,以防意外从类中调用构造函数。它保证类在任何情况下都不会被实例化。这个习语有点违反直觉,因为构造函数是明确提供的,因此无法调用它。因此,如上所示,包含注释是明智的。
作为一个副作用,这个习惯用法还可以防止类被子类化。所有构造函数都必须显式或隐式调用超类构造函数,并且子类将没有可访问的超类构造函数来调用。
听起来您有一个类似于java.lang.Math的实用程序类。
该方法是具有私有构造函数和静态方法的最终类。
但是要注意这对可测试性有什么影响,我建议阅读这篇文章
静态方法是可测试性的死亡
只是为了逆流而上,静态成员和类不参与 OO,因此是邪恶的。不,不是邪恶的,但说真的,我会推荐一个带有单例模式的普通类来访问。这样,如果您在以后的任何情况下都需要覆盖行为,那么这不是重大的重组。OO 是你的朋友 :-)
我的 $.02
评论“私有构造函数”的论点:来吧,开发者没那么傻;但他们很懒惰。创建一个对象然后调用静态方法?不会发生。
不要花太多时间来确保您的课程不会被滥用。对你的同事有一些信心。无论您如何保护它,总有一种方法可以滥用您的课程。唯一不能被滥用的是完全没用的东西。
- 最终类和私有构造函数(很好但不是必需的)
- 公共静态方法
将类声明为static
. 只需声明它的方法static
并像往常一样从类名中调用它们,就像 Java 的Math类一样。
此外,即使将构造函数设为私有并不是绝对必要的,但这样做也是一个好主意。将构造函数标记为私有可防止其他人创建您的类的实例,然后从这些实例调用静态方法。(这些调用在 Java 中的工作方式完全相同,它们只会误导并损害代码的可读性。)