Java: 静态类?

137

我有一个充满实用函数的类。实例化它没有语义意义,但我仍然想调用它的方法。最好的处理方式是什么?静态类?抽象类?


16
顺便提一下,您无法将顶级类设置为静态的。 - Jonathan Holloway
8个回答

170

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


21
如David Robles在他的回答中指出,你不需要将这个类设为final…因为它无法被子类化,原因是子类无法调用父类构造器,因为它是私有的。然而,明确一点也没有坏处。但jfyi:-)。 - Tom

96

根据伟大的书籍《Effective Java》

条款4:通过私有构造函数强化非实例化能力

- 尝试通过使类变为抽象类来强制防止实例化无效。

- 只有在类中不包含显式构造函数时才会生成默认构造函数,因此可以通过包括一个私有构造函数使一个类成为不可实例化的:

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

由于显式构造函数是私有的,因此在类外部无法访问。 AssertionError不是必需的,但它可提供保险措施,以防意外从类内调用构造函数。它保证该类在任何情况下都不会被实例化。这种习惯用法略微反直觉,因为提供了构造函数却又明确禁止其被调用。因此,最好包含如上所示的注释。

作为副作用,这种习惯用法还可以防止该类被子类化。 所有构造函数都必须显式或隐式地调用超类构造函数,而子类将没有可访问的超类构造函数可供调用。


1
你为什么选择AssertionError而不是其他替代方案,比如IllegalStateExceptionUnsupportedOperationException等? - Pacerier
@Pacerier 请参考这里 - bcsb1001
@bcsb1001,这就带我们来到了这里 - Pacerier

21

2
那么 java.lang.Math 是否“致命于可测试性”? - Pacerier
1
当通过https://code.google.com/p/testability-explorer/运行时,看到它的得分可能会很有趣。 - crowne

6

仅仅为了激进一些,静态成员和类不参与面向对象编程,因此它们是邪恶的。不,不是邪恶的,但是我建议使用常规类和单例模式进行访问。这样,如果需要在将来的任何情况下覆盖行为,它不会是一个重大的重新工具化。面向对象编程是你的朋友 :-)

我的观点


19
单例模式也被认为是有害的。 - Dan Dyer
3
使用私有构造函数可以防止任何人实例化或继承这个类。请参考David Robles的回答:https://dev59.com/WHI-5IYBdhLWcg3wc4Cw#1844388 - rob
5
单例模式并没有比依赖注入更加邪恶 :) - irreputable
13
面向对象编程有其应用场景,但有时候并不实用,或者会浪费资源——比如像 Math.abs() 这样的简单功能。如果只是为了创建一个对象而创建对象,那么完全没有必要,因为可以直接调用静态方法来完成任务,避免了面向对象带来的额外开销。 ;) - rob
2
@rob 关于OO,我同意,Math.Abs可能永远不需要一个实例。当我听到“我有一个实用类”的时候,我会想到Math.Avg(),现在你需要添加支持加权平均值。我看到一个URL生成器,参数输入,URL输出,需要重构以支持href或仅URL等等。出于这些原因,拥有基于OO的实用类可以得到回报。此外,现在我将放弃标准的OO防御策略,测试!/我躲开 - Bennett Dill
显示剩余4条评论

3

关于“私有构造函数”的参数的评论:开发人员并不那么愚蠢,但他们确实很懒。创建对象然后调用静态方法?不可能发生。

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


8
我看过(在生产代码中,而不仅仅是学生代码中)object.staticMethod 的人认为你高估了普通程序员 Joe!:-P - TofuBeer

2
  • Final类和私有构造函数(好但非必要)
  • 公共静态方法

1

将类声明为static没有意义。只需将其方法声明为static,然后像Java的Math类一样从类名调用它们即可。

此外,尽管将构造函数设为私有并不是严格必要的,但这是一个好主意。将构造函数标记为私有可以防止其他人创建类的实例,然后从这些实例调用静态方法。(在Java中,这些调用的工作方式完全相同,只是会误导并影响代码的可读性。)


1
另外,不要忘记创建一个私有构造函数。 - Asaph
@Asaph:同意。我在我的答案中加了一点关于这个的内容。谢谢。 - Bill the Lizard
如果你想在内部类中使用静态方法,那么这个类也必须是静态的。 - Rui Marques

-1

点击链接,这是实验性的,不建议使用(“由于非星号静态导入存在根本问题”)。 - jedwidz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接