Java静态方法的优点和缺点

我之前没有使用过很多静态方法,但最近我倾向于使用更多静态方法。 例如,如果我想在类中设置一个布尔标志,或者需要在一个类中设置一个布尔标志,而不需要通过类传递实际的对象。

例如:

public class MainLoop { private static volatile boolean finished = false; public void run() { while ( !finished ) { // Do stuff } } // Can be used to shut the application down from other classes, without having the actual object public static void endApplication() { MainLoop.finished = true; } } 

这是我应该避免的吗? 传递一个对象以便使用对象方法更好吗? 布尔finished现在是否计为全局,或者它是否同样安全?

在这种情况下使用静态变量的一个问题是,如果您创建两个(或更多)MainLoop实例,编写看起来像它的代码只关闭其中一个实例,实际上将关闭它们:

 MainLoop mainLoop1 = new MainLoop(); MainLoop mainLoop2 = new MainLoop(); new Thread(mainLoop1).start(); new Thread(mainLoop2).start(); mainLoop1.finished = true; // static variable also shuts down mainLoop2 

这只是选择不使用静态变量的一个原因(众多)。 即使您的程序今天只创建了一个MainLoop,但未来您可能有理由创建其中许多:用于unit testing,或实现一个很酷的新function。

您可能会想“如果发生这种情况,我只会重构程序以使用成员变量而不是静态变量。” 但是,预先支付成本通常更有效,并且从一开始就将模块化设计融入到程序中。

毫无疑问,静态通常会使快速而肮脏的程序更容易编写。 但是对于您打算在未来几年内测试,维护,增长,共享和使用的重要/复杂代码,通常建议使用静态变量。

正如对这个问题的其他答案所指出的,静态变量是一种全局变量。 关于为什么(通常) 全局 变量 是 坏的 ,有很多信息。

是的,传递物体更好。 使用单例或静态方法使OO编程看起来像过程编程。 单例有点好,因为你至少可以使它实现接口或扩展抽象类,但它通常是一种设计气味。

将实例方法与你正在做的静态变量混合起来更加令人困惑:你可以让几个对象循环,但你会立刻停止它们,因为它们都会在静态变量发生变化时停止。

这是我应该避免的吗?

一般来说,是的。 静力学代表全球状态。 全局状态很难推理,很难单独测试,并且通常具有更高的线程安全性要求。

如果我想测试某个状态下对象会发生什么,我可以创建该对象,将其置于该状态,执行我的测试,并让它被垃圾收集。

如果我想测试全局状态会发生什么,我需要确保在测试结束时(或者可能在每次测试开始时)重置所有状态。 如果我不小心这样做,测试现在会相互干扰。

当然,如果静态方法不需要影响任何状态 – 即它是纯粹的 – 那么它会变得更好一些。 在那一点上,你失去的就是能够替换那个方法实现,例如在测试调用它的东西时。

通常,通过像这样创建finished静态,您创建的情况是,任何时候都只能run一个MainLoop类的实例。 如果有多个实例,则设置finished将结束它们 – 而不是通常所需的。

但是,在这种特殊情况下,您希望“结束应用程序”,可能意味着您希望结束MainLoop所有实例,这种方法可能是合理的。

但是,这种方法可能值得的情况很少,处理这种情况的“更清洁”的方法是保持static的实例列表并在列表中工作,在每个实例中设置实例变量。 这允许您也结束单个实例,为您提供现有实例的自然计数等。