公用事业类应该是静态的吗?

nib*_*012 70 java

如果我必须设计一个Utility类(例如ByteUtils或StreamUtils或StringUtils),那么它们的最佳设计选择是什么.

  • 它们应该是静态类(因为我没有任何状态存储)
  • 它们应该是非静态类(如果不使用对象,它们将被gc'd)

PS:通过静态类,我的意思是一个带有静态方法的类(而不是内部静态类)

请就此设计选择提出建议?

JB *_*zet 63

我的实用程序类看起来像这样:

// final, because it's not supposed to be subclassed
public final class FooUtil {

    // private constructor to avoid unnecessary instantiation of the class
    private FooUtil() {
    }

    public static int doSomethingUseful() {
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,尽管这使得实用程序方法易于测试,并且可以从外部轻松访问,但它也使得使用它们的类难以进行单元测试,因为模拟这些实用程序方法并不容易.有太多这样的实用程序类可能是缺乏OO设计(程序编程)的标志,并且可能真的使代码难以测试.

如果您正在使用依赖注入框架(Spring,Guice,无论如何),那么使用非静态方法使实用程序类可实例化并使其成为可注入的单例可能是个好主意.这样,可以通过模拟实用程序对象来测试使用这些实用程序方法的类.

  • @ nibin012只是因为你可以,并不代表你应该.在我的项目中,PowerMock是一种不断悲伤的工具 - 它与其他工具一样糟糕,因为它与类加载器混淆得太多了. (10认同)
  • 我们可以使用powermock http://code.google.com/p/powermock/对静态方法进行单元测试 (2认同)
  • “如果您正在使用依赖注入框架” - 如果没有,那么这是一个坏主意? (2认同)

Gap*_*ton 45

如果它是一个通用的实用程序,静态是IMO更好.你声明你不会有任何州存储,所以我不明白你为什么要把它作为非静态的.声明它是静态的也会节省内存.

  • 这适用于所有不依赖于对象状态的方法.不仅仅是实用类方法. (9认同)
  • 螺丝刀不会改变,它总是做同样的事情.如果你的实用程序类可以说同样的话,那肯定是静态的. (7认同)

小智 24

仅仅因为某些东西可以是静态的,并不意味着它应该是静态的.

所有这一切都有另一个考虑因素:嘲弄.在测试中模拟静态方法比模拟类实例的行为更困难.

谈论不必要的堆分配和对象的GCing对我来说过早优化.JVM在优化这类问题方面做得非常好.


Pet*_*rey 9

定义Utility类的最简单方法是作为没有实例的枚举

public enum Utility {;
     public static int utilityMethod(int x) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)

实用程序类不应该具有任何状态或具有最小状态,因此您不应该担心GC.

您可以将其他有状态类用于特定目的,例如Builder,Factory,您可以根据需要创建对象,并在完成后将其丢弃.

  • 我真正在这里做的*主要*点是当你使用`enum`时,你正在向读者传达有一个隐藏在其设计中的枚举理由.没有.你只是试图让它变得比放入`final`和私有构造函数更容易,这两者都不是IMO的问题.这是一个不寻常的习语.你看到有人试图实例化一类实用的静态方法?这有关系吗?如果有人看到这个类提供他们需要的方法,他们就会知道它们是什么----*为什么*它们会实例化它?如果他们这样做会发生什么?不多. (4认同)
  • @PeterLawrey,虽然这是真的,但它对我来说太过工程了.从1996年开始,我可以计算零次的总和,我看到有人意外地实例化了一个简单的静态实用程序.提供这样的保护是愚蠢的IMO,因为实例化这样的事情的后果是你立即注意到它将无法工作.然而,将"enum"放入混合物会改变疲倦的工程师在凌晨3点跳上咖啡因会如何读取这个东西并让他想知道发生了什么.这不是一个常见的习语.使用`class`并且快乐. (3认同)
  • 我想我们一直需要质疑一些过度保护的思想.对于冒险,避免多次退货,实例化保护等等,对所有这些都非常有限.然而***值得保护的***是代码的可读性.始终尽量保持尽可能接近无脑的范畴. (3认同)

小智 6

最好使用私有构造函数使类成为非静态类:

  • 如果我们将类设为静态,则在部署应用程序时将加载该类,如果它是非静态的,则在调用其静态方法之一时将加载该类
  • 创建私有构造函数将避免实例化该类