我有一个充满实用函数的类。实例化它没有语义意义,但我仍然想调用它的方法。最好的处理方式是什么?静态类?抽象类?
私有构造函数和被标记为final的类上的静态方法。
根据伟大的书籍《Effective Java》:
条款4:通过私有构造函数强化非实例化能力
- 尝试通过使类变为抽象类来强制防止实例化无效。
- 只有在类中不包含显式构造函数时才会生成默认构造函数,因此可以通过包括一个私有构造函数使一个类成为不可实例化的:
// Noninstantiable utility class
public class UtilityClass
{
// Suppress default constructor for noninstantiability
private UtilityClass() {
throw new AssertionError();
}
}
由于显式构造函数是私有的,因此在类外部无法访问。 AssertionError不是必需的,但它可提供保险措施,以防意外从类内调用构造函数。它保证该类在任何情况下都不会被实例化。这种习惯用法略微反直觉,因为提供了构造函数却又明确禁止其被调用。因此,最好包含如上所示的注释。
作为副作用,这种习惯用法还可以防止该类被子类化。 所有构造函数都必须显式或隐式地调用超类构造函数,而子类将没有可访问的超类构造函数可供调用。
听起来你有一个类似于java.lang.Math的实用类。
那里的方法是使用final类和私有构造函数以及静态方法。
但要注意这对可测试性的影响,我建议阅读这篇文章
Static Methods are Death to Testability
仅仅为了激进一些,静态成员和类不参与面向对象编程,因此它们是邪恶的。不,不是邪恶的,但是我建议使用常规类和单例模式进行访问。这样,如果需要在将来的任何情况下覆盖行为,它不会是一个重大的重新工具化。面向对象编程是你的朋友 :-)
我的观点
关于“私有构造函数”的参数的评论:开发人员并不那么愚蠢,但他们确实很懒。创建对象然后调用静态方法?不可能发生。
不要花太多时间来确保您的类不会被误用。对您的同事有信心。无论如何保护它,总有一种方法可以误用您的类。唯一不能被误用的东西是完全没用的东西。
将类声明为static
没有意义。只需将其方法声明为static
,然后像Java的Math类一样从类名调用它们即可。
此外,尽管将构造函数设为私有并不是严格必要的,但这是一个好主意。将构造函数标记为私有可以防止其他人创建类的实例,然后从这些实例调用静态方法。(在Java中,这些调用的工作方式完全相同,只是会误导并影响代码的可读性。)
您可以使用Lombok的@UtilityClass注解https://projectlombok.org/features/experimental/UtilityClass