134

我有一个充满实用功能的类。实例化它的实例没有语义意义,但我仍然想调用它的方法。处理这个问题的最佳方法是什么?静态类?抽象的?

4

8 回答 8

167

标记为 final 的类上的私有构造函数和静态方法。

于 2009-12-04T01:43:12.880 回答
93

根据伟大的书“Effective Java”

第 4 条:使用私有构造函数强制执行不可实例化

- 试图通过使类抽象来强制执行不可实例化是行不通的。

- 仅当类不包含显式构造函数时才会生成默认构造函数,因此可以通过包含私有构造函数使类不可实例化:

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

因为显式构造函数是私有的,所以在类之外是不可访问的。AssertionError 不是严格要求的,但它提供了保险,以防意外从类中调用构造函数。它保证类在任何情况下都不会被实例化。这个习语有点违反直觉,因为构造函数是明确提供的,因此无法调用它。因此,如上所示,包含注释是明智的。

作为一个副作用,这个习惯用法还可以防止类被子类化。所有构造函数都必须显式或隐式调用超类构造函数,并且子类将没有可访问的超类构造函数来调用。

于 2009-12-04T01:47:09.877 回答
21

听起来您有一个类似于java.lang.Math的实用程序类。
该方法是具有私有构造函数和静态方法的最终类。

但是要注意这对可测试性有什么影响,我建议阅读这篇文章
静态方法是可测试性的死亡

于 2009-12-04T06:50:50.823 回答
6

只是为了逆流而上,静态成员和类不参与 OO,因此是邪恶的。不,不是邪恶的,但说真的,我会推荐一个带有单例模式的普通类来访问。这样,如果您在以后的任何情况下都需要覆盖行为,那么这不是重大的重组。OO 是你的朋友 :-)

我的 $.02

于 2009-12-04T01:53:41.923 回答
3

评论“私有构造函数”的论点:来吧,开发者没那么傻;但他们很懒惰。创建一个对象然后调用静态方法?不会发生。

不要花太多时间来确保您的课程不会被滥用。对你的同事有一些信心。无论您如何保护它,总有一种方法可以滥用您的课程。唯一不能被滥用的是完全没用的东西。

于 2009-12-04T02:42:12.343 回答
2
  • 最终类和私有构造函数(很好但不是必需的)
  • 公共静态方法
于 2009-12-04T03:16:18.497 回答
1

将类声明为static. 只需声明它的方法static并像往常一样从类名中调用它们,就像 Java 的Math类一样。

此外,即使将构造函数设为私有并不是绝对必要的,但这样做也是一个好主意。将构造函数标记为私有可防止其他人创建您的类的实例,然后从这些实例调用静态方法。(这些调用在 Java 中的工作方式完全相同,它们只会误导并损害代码的可读性。)

于 2009-12-04T01:44:33.607 回答
0

您可以使用来自 lombok https://projectlombok.org/features/experimental/UtilityClass的 @UtilityClass 注释

于 2020-05-21T06:25:56.837 回答