为什么OOP中静态类的最佳实践会有所不同?

我目前正在阅读有关Java最佳实践的内容,我发现根据本书,我们必须支持静态类而非非静态类 。 我记得在C#最佳实践中,我们必须根据Dennis Doomen的C#3.0,4.0和5.0编码指南来避免这种情况:

AV1008避免静态类

除了扩展方法容器之外,静态类通常会导致设计错误的代码。 除非你愿意使用一些非常黑客的工具,否则即使不是不可能,它们也是非常困难的。 注意如果您确实需要该静态类,请将其标记为静态,以便编译器可以阻止实例成员并实例化您的类。 这可以减轻您创建显式私有构造函数的麻烦。

我发现这两个用于C#答案和Java答案何时使用和避免静态类,但仅仅是好奇心 – C#和Java都是OOP语言,为什么它在最佳实践中是完全不同的?

更新:我不能从Java书中复制这么多页面,但底线是:

如果声明一个不需要访问封闭实例的成员类,则始终将static修饰符放在其声明中,使其成为静态成员类而非非静态成员类。 如果省略此修饰符,则每个实例将对其封闭实例具有无关的引用。 存储此引用会花费时间和空间,并且可能导致封闭实例被保留,否则它将有资格进行垃圾回收(第6项)。 如果您需要分配没有封闭实例的实例,您将无法这样做,因为非静态成员类实例需要具有封闭实例。 私有静态成员类的常见用法是表示由其封闭类表示的对象的组件。

它只是关于性能吗?

注意,这个问题更多的是关于静态类和OOP ,而不是Java和C#之间的差异。

JoshuaBloch给出的建议也适用于c#,而为c#提供的建议也适用于java(在谈论静态类时)。

为何使用静态成员?

  • 他们不需要实例来调用它们
  • 在c#中,他们使用调用操作码 ,它不需要检查null (这是一个微优化),而不是实例方法(使用callvirt操作码 )。 我相信类似的东西也会出现在java中。
  • 如果不使用实例,它们不会阻止GC中的某些内容。
  • 也没有this引用传递给隐藏的所有方法的开销。

如果您习惯于Visual Studio的Resharper生产力工具,它将提供与JoshuaBloch给出的相同的建议,在c#中说Method可以是静态的 ,这在给定的链接中是合理的。

为什么不使用静态成员?

  • 它们不可测试(容易)。
  • 他们无法实现接口成员。
  • 它们不能通过dependency injection注入。
  • 它们不参与多态(在面向对象语言中非常需要)。
  • 在c#中,静态类不能作为引用传递。

因此,如果您了解它们并且它们适用于这两种语言,这两个建议都很好。 在适当时使用它们,当它们不适合时避免使用它们。

  1. 我认为第二个文本片段是关于member classenclosing ,这是特定于Java的特性(如何实现)。
  2. 静态类或字段(如在C#中)实际上是糟糕的设计实践 – 看看OOP和SOLID。 此外,它可能会导致CLR级别的一些性能问题。 但私有静态方法没有错。 我记得,Resharper建议将私有方法独立于具体实例静态。 它增加了可读性并且没有副作用。 而且你不需要unit testing私有方法。 这也是不好的做法。
  3. 最后,一些作者简要介绍了技术和一些 – 关于设计原则。 通常这些观点之间存在矛盾(但描述的两个片段与此无关)。