之前我没有使用过很多静态方法,但最近我倾向于使用更多静态方法。例如,如果我想在类中设置一个布尔标志,或者在没有需要通过类传递实际对象的情况下设置一个布尔标志。
例如:
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
现在算作全局,还是安全?
答案 0 :(得分:6)
是的,传递物体更好。使用单例或静态方法使OO编程看起来像过程编程。单例有点好,因为你至少可以让它实现接口或扩展抽象类,但它通常是一种设计气味。
将实例方法与你正在做的静态变量混合起来更加令人困惑:你可以让几个对象循环,但是你会立刻停止它们,因为它们都会在静态变量发生变化时停止。
答案 1 :(得分:5)
这是我应该避免的吗?
总的来说,是的。静态表示全局状态。全局状态难以推理,难以单独测试,并且通常具有更高的线程安全要求。
如果我想测试某个状态下对象会发生什么,我可以创建该对象,将其置于该状态,执行我的测试,并让它被垃圾收集。 / p>
如果我想测试全局状态会发生什么,我需要确保在测试结束时(或者可能在每次测试开始时)重置所有内容。如果我不小心这样做,测试现在会相互干扰。
当然,如果静态方法不需要影响任何状态 - 即如果它纯 - 那么它会变得更好一些。此时,您失去的是替换该方法实施的能力,例如:在测试调用它的东西时。
答案 2 :(得分:5)
在这种情况下使用静态变量的一个问题是,如果您创建两个(或更多)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,但未来您可能有理由创建其中的许多:用于单元测试,或实现一个很酷的新功能。
您可能会想到,如果发生这种情况,我只是重构程序以使用成员变量而不是静态变量。"但是,预先支付成本通常更有效,并且从一开始就将模块化设计融入到程序中。
毫无疑问,静态通常会使快速而肮脏的程序更容易编写。但是对于您打算在未来几年内测试,维护,增长,共享和使用的重要/复杂代码,通常建议使用静态变量。
正如这个问题的其他答案所指出的,静态变量是一种全局变量。还有很多关于为什么(通常)global variables are bad的信息。
答案 3 :(得分:2)
通常,通过使finished
静态,您创建的情况是,任何时候只有一个MainLoop
类的实例执行run
。如果有多个实例,则设置finished
将结束所有实例 - 而不是通常所需的内容。
但是,在这个特定的场景中,您希望结束应用程序",可能意味着您希望结束MainLoop
的所有实例,方法可能是合理的。
然而,这种方法可能值得采用的情况很少,并且“#”更清洁"处理此方案的方法是保留static
实例列表并完成列表,在每个实例中设置实例变量finished
。这允许您也结束单个实例,为您提供现有实例的自然计数等。