为什么 OOP 中静态类的最佳实践各不相同?

eko*_*nov 5 c# java oop static

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

AV1008 -避免静态类

除了扩展方法容器之外,静态类通常会导致设计错误的代码。除非您愿意使用一些非常hacky 的工具,否则它们也很难(如果不是不可能)单独测试。注意如果您确实需要该静态类,请将其标记为静态,以便编译器可以防止实例成员和实例化您的类。这使您无需创建显式私有构造函数。

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

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

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

那么它只是关于性能吗?

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

Sri*_*vel 7

JoshuaBloch 给出的建议也适用于 c#,而为 c# 给出的建议也适用于 java(在某种程度上,他们谈论的是静态类)。

为什么要使用静态成员?

  • 他们不需要实例来调用它们
  • 在 c# 中,他们使用call opcode,它不需要检查null(这是一个微优化),而不是实例方法(它使用callvirt opcode)。我相信java中也会有类似的东西。
  • 如果不使用实例,它们不会阻止 GC 发生的事情。
  • 也没有传递this对所有隐藏方法的引用的开销。

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

为什么不使用静态成员?

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

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