为什么面向对象编程中静态类的最佳实践因情况而异?

6
我正在学习Java最佳实践,根据这本书的说法,我们应该静态类优于非静态类。我记得在C#最佳实践中,根据Dennis Doomen的《Coding Guidelines for C# 3.0、4.0和5.0》指南,我们必须避免使用静态类:

AV1008 - 避免使用静态类

除了扩展方法容器之外,静态类经常导致设计不良的代码。除非您愿意使用一些非常糟糕的工具进行测试,否则它们也很难甚至不可能单独测试。请注意如果您确实需要那个静态类,请将其标记为静态类,以便编译器可以防止实例成员和实例化您的类。这使您免于创建显式私有构造函数。

我在C#的答案Java的答案中找到了关于何时使用和避免静态类的解释,但只是出于好奇——C#和Java都是面向对象的语言,为什么最佳实践存在如此大的差异呢? 更新: 我无法在这里复制太多Java书页,但底线是:

如果声明不需要访问封闭实例的成员类,则始终在其声明中放置static修饰符,使其成为静态而非非静态成员类。如果省略此修饰符,则每个实例将拥有一个对其封闭实例的额外引用。存储此引用会耗费时间和空间,并且可能导致保留封闭实例,而当它本来应该被垃圾回收时(第6项)。如果您曾经需要分配没有封闭实例的实例,那么您将无法这样做,因为要求非静态成员类实例具有封闭实例。私有静态成员类的常见用途是表示其封闭类所表示的对象的组件。

所以这只是关于性能问题吗? 请注意,这个问题更多的是关于静态类和面向对象编程,而不是Java和C#之间的区别。

那本书的作者是否给出了静态类优于非静态类的原因? - Dirk
1
我也一直在想这个关于Python的问题... Pycharm(一个用于Python的 IDE)一直在我的代码中添加警告,说方法可以被声明为静态,这让我很疯狂。 - Sayse
2
不是这种问题的正确论坛。 - Robert Langdon
2
我认为您从书中缺少了上下文,您需要提供书籍摘录以便进行判断。 - Mateusz
我知道有一些不好的做法,但最好的做法,我并不确定。 - TaW
3
在C#和Java中,静态类使用相同的关键字,但它们并不是相同的概念,存在根本性的区别。 - Mark Rotteveel
2个回答

9
JoshuaBloch提出的建议也适用于C#,C#中提出的建议也适用于Java(某种程度上,因为它们讨论静态类)。
为什么要使用静态成员?
- 它们不需要实例来调用它们 - 在c#中,它们使用call opcode,不需要检查null(这是一种微小的优化),而实例方法则使用callvirt opcode。我相信在Java中也会有类似的情况。 - 如果未使用实例,则它们不会阻止GC - 同样没有传递this引用到所有隐藏方法的开销。
如果您习惯于使用Visual Studio的Resharper生产力工具,它会给出与JoshuaBloch在Java中给出的相同建议,即在C#中说方法可以被设置为静态,这在给定的链接中是有道理的。

为什么不使用静态成员?

  • 它们不易进行测试。
  • 它们无法实现接口成员。
  • 它们无法通过依赖注入进行注入。
  • 它们不参与多态(这在面向对象语言中非常重要)。
  • 在C#中,静态类无法作为引用传递。
因此,这两个建议都很好,如果您理解它们并且它们适用于这两种语言。当它们合适时请使用它们,否则请避免使用它们。

最好使用静态类而不是单例模式。大多数静态类也可以做到线程安全。 - Aniket Inge
@Aniket 我不明白。为什么?静态本身并不具备线程安全性。我们需要为线程安全付费。此外,单例类必须是线程安全的。 - Sriram Sakthivel
可以是... 不代表它们默认就是。 - Aniket Inge
我想说的是它们可以被制作成线程安全的单例。 - Aniket Inge
@Aniket,是吗?经典的单例实现对类客户端透明,而静态则不然。一旦将某个类设为静态,您就会放弃所有面向对象编程的好处,因为至少(!)静态类无法派生或继承。 - Valentin P.
而且静态字段可能会导致内存泄漏。如果有人忘记将静态字段值设置为null,那么GC无法收集相关的对象图 - 静态字段永远不会被GC豁免。 - Valentin P.

3
  1. 我认为第二段文字是关于成员类封闭的,这是Java特有的功能(它如何实现)。
  2. 静态类或字段(如C#中)实际上是糟糕的设计实践 - 请查看OOP和SOLID。此外,它可能会导致CLR级别的性能问题。但是私有静态方法没有任何问题。据我记得,Resharper建议使私有方法独立于具体实例静态化。这可以增加可读性而且没有副作用。您不需要对私有方法进行单元测试,这也是不好的实践。
  3. 最后,一些作者简要介绍技术,一些作者则介绍设计原则。这些观点之间经常存在矛盾(但描绘的两个片段不是关于矛盾的)。

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