Answers:
请注意,IDEA也对此Java进行了检查,这被称为Method可能是'static',
此检查报告可以安全地设置为静态的任何方法。如果某个方法未引用其类的任何非静态方法和非静态字段,并且未在子类中覆盖,则该方法可能是静态的。
尽管对于Java代码来说,默认情况下是关闭了此检查的(程序员可以自行决定将其打开)。其原因很可能是基于几个相当权威的资料来质疑这种检查的有效性/有用性。
首先,正式的Java教程对方法应为静态的时间有严格的限制:
静态方法的常见用法是访问静态字段。
综上所述,有人可能会争辩说,默认情况下打开提到的检查不符合Java中对静态修饰符的建议使用。
此外,还有其他一些消息来源建议采用明智的方法来使用这种检查背后的想法,甚至不鼓励这样做。
例如,参见Java World文章-Happy Object先生教授静态方法:
任何与实例状态无关的方法都可以被声明为静态方法。
请注意,我说“被声明为静态的候选者”。即使在前面的示例中,也没有什么迫使您声明
instances()
为静态的。将其声明为静态只会使调用更加方便,因为您不需要实例来调用该方法。有时,您将拥有似乎不依赖实例状态的方法。您可能不想使这些方法静态化。实际上,如果您需要在没有实例的情况下访问它们,则可能只想将它们声明为静态。而且,即使可以将这种方法声明为静态方法,也可能由于其插入设计中的继承问题而不想这样做。看看“有效的面向对象设计”,您将看到一些问题。
Google测试博客上的一篇文章甚至宣称静态方法是可测试性的死亡:
让我们进行精神锻炼。假设您的应用程序只有静态方法。(是的,可以编写这样的代码,称为过程编程。)现在想象该应用程序的调用图。如果尝试执行叶子方法,则设置其状态并断言所有极端情况都没有问题。原因是叶子方法不再进行任何调用。随着您离叶子越来越远,更接近于根
main()
方法,在测试中建立状态的难度将越来越大,而声明事物的难度也将越来越大。许多事情将变得无法断言。您的测试将逐渐变大。一旦到达main()
方法,您不再需要进行单元测试(因为您的单元是整个应用程序),您现在有了场景测试。假设您要测试的应用程序是文字处理器。您可以从main方法中断言很多...有时静态方法是其他对象的工厂。这进一步加剧了测试问题。在测试中,我们依靠这样的事实,即我们可以用不同的方式连接对象,并用模拟替换重要的依赖关系。一旦
new
经营者被称为我们不能覆盖使用一个子类中的方法。这种静态工厂的调用者永久绑定到静态工厂方法生成的具体类。换句话说,静态方法的损害远远超出静态方法本身。将对象图接线和构造代码对接成静态方法特别糟糕,因为对象图接线是我们隔离测试对象的方式。
您会发现,上面给出的Java默认情况下被关闭检查是很自然的。
IDE开发者将有一个真的很难解释为什么他们认为作为默认设置它,对广泛认可的建议和最佳做法,它是如此重要。
对于Groovy而言,情况大不相同。上面列出的论点均不适用,尤其是关于可测试性的论点,如Javalobby 在Groovy中模拟静态方法一文中所述:
如果您要测试的Groovy类在另一个Groovy类上调用了静态方法,则可以使用ExpandoMetaClass,它允许您动态添加方法,构造函数,属性和静态方法...
这种差异可能是为什么Groovy中提到的检查的默认设置相反的原因。在Java中,默认情况下“ on”会引起用户混乱,而在Groovy中,相反的设置可能会使IDE用户感到困惑。
“嘿,该方法不使用实例字段,为什么不警告我呢?” 对于Java(如上所述),这个问题很容易回答,但是对于Groovy而言,没有令人信服的解释。
很难想象这会对性能产生任何明显的影响。我能看到的唯一好处static
是它提供了实例状态不受影响的视觉指示。换句话说,它告诉正在阅读源代码的人某些东西……仅仅因为它存在而对该方法“很感兴趣”。真正的问题是,它澄清还是造成混淆? “为什么该方法是静态的?它是工厂方法吗?不需要对象实例就可以调用它吗?”
另外,有些人不喜欢静态方法,因为他们声称您无法模拟它们,因此它们不可测试,或者类似的东西。当然,如果您出于任何通常的原因将其设置为静态,例如提供工厂方法,那么我全力以赴。我只是不太确定使方法成为静态方法(仅因为它们不接触实例状态)是强制性的。
final
或专门考虑继承来设计。