Java 我应该在这里使用全局变量吗?

Java 我应该在这里使用全局变量吗?,java,global-variables,Java,Global Variables,为什么使用全局变量是个坏主意 我想让所有类都可以使用一个变量数组。它将存储密钥状态,因此不能设置为const(final) 你能告诉我其他(正确的)方法吗 为什么使用全局变量是个坏主意 因为它破坏了封装。所有代码都可以访问和修改它们 我想让所有类都可以使用变量数组 如果所有代码只使用一个实例,则可以使用单实例: public class MyGlobalKeys { private static final MyGlobalKeys globals = new MyGlobalKeys(

为什么使用全局变量是个坏主意

我想让所有类都可以使用一个变量数组。它将存储密钥状态,因此不能设置为const(final)

你能告诉我其他(正确的)方法吗

为什么使用全局变量是个坏主意

因为它破坏了封装。所有代码都可以访问和修改它们

我想让所有类都可以使用变量数组

如果所有代码只使用一个实例,则可以使用单实例:

public class MyGlobalKeys {
    private static final MyGlobalKeys globals = new MyGlobalKeys();

    // disable construction outside of this class
    private MyGlobalKeys() {}

    public void getInstance() {
       return globals;
    }

    public void addKey(String key, bool state) { ... }
    public bool hasKey(String key) { ... }
    // and so on ...
}

请注意,此示例尤其不具有线程安全性-有关改进的实现方法,请参见

我的个人经验是:如果您开始使用全局变量(或任何类似于全局变量的行为),您将一次又一次地使用它。最后,你会发现自己陷入了一个意大利面代码池

另一方面,我无法想象为什么所有(!)其他类都应该使用键状态

我建议考虑一位专家来存储这些状态。这个专家将是你的关键国家级

为什么使用全局变量是个坏主意

除非它们是用来指示已知常数的,否则全局变量会引入我们称之为可变全局状态的变量。这与单个对象具有可变数据成员时的情况形成对比,即对象状态

考虑一个接受一些参数、执行某些操作并返回值的方法

最理想的场景(从分析代码、调试、测试等的角度来看)是,如果使用相同(或相等)参数调用相同(或相等)对象,则此方法将执行相同的操作。这对于不可变对象(具有不可变对象状态的对象)很容易实现

最常见的场景(在实践中)是,方法的行为将取决于对象的状态和参数,这意味着如果对象的状态已更改(可变对象),则对于具有相同(或相等)参数的多个调用,方法的行为可能不同。这不是很理想,但它仍然可以很容易地使用

最不希望出现的情况是方法依赖于全局状态。对同一(或相等)对象使用相同(或相等)参数多次调用同一方法可能会产生不同的结果。即使该对象在调用中处于等效状态,或者即使它是不可变的!这显然是很难处理的,因为如果你怀疑一个方法没有完成它应该做的事情,你就不能在任何你想要的地方测试它的行为。你必须测试它,至少是针对你正在处理的具体案例(可能并不总是像听起来那么简单),然后针对你能想到的每一个案例,它都会被使用,并且经常会有你会错过的重要案例。你不能总是相信这种方法

这不是为什么不应该使用全局变量的解释,而是为什么它们通常被认为是不好的做法

我个人使用的另一个例子是,如果您使用一段最初用于执行一个操作的代码,并让它在同一个会话中执行多次(例如,将其粘贴到GUI上)。在这种情况下,除第一次运行外,每次运行操作都会发现程序处于通常不可预测的状态。这将产生尴尬的效果,即程序中的某个操作在第一次执行时将正确运行,并且每隔一次都有可能错误运行,直到程序关闭并再次运行

我使用的另一个例子(如果前一段没有说服力的话)是:如果前一段的例子是这样的,但是是平行的呢?在这种情况下,执行相同操作的多个线程将在极不可预测的点上改变彼此的状态

你能告诉我其他(正确的)方法吗


在我看来,构建程序的正确方法是将方法应使用的状态作为一个或多个参数传递给(并让它将该状态传递给它调用的方法,如果它们也需要此信息)。

非常量的全局变量,糟糕的设计有很多原因,基本上是因为它们破坏了封装。全局变量确保您的类不能有两个不同的实例(单实例遇到类似的问题)

它们将使单元测试代码变得更加困难,并且使并行化代码变得不可能。考虑一个场景,其中有处理输入文件的代码。每个输入文件都与其他文件分开。您希望处理整个目录,为了利用新的多核服务器,您决定使用线程一次处理4个文件。 据推测,这应该非常简单,因为处理任务完全不相关,因此不需要同步。但是,由于使用了全局变量,因此在代码的不同实例之间引入了全局相互依赖关系,因此线程之间的内部状态会相互干扰,导致代码无法工作

这是一个反对天真地使用全局状态的论点。这种方法有几种合法用途,但每种情况都必须根据其本身的是非曲直进行辩论


至于正确的方法,我将创建一个
State
类,并将其传递给所有需要它的类的构造函数。

你所说的“键状态”是什么意思?为什么不创建一个包含一些静态成员和方法的单独类?相关:编辑实际上显示了你的意思。你能举一个使用它的例子或者解释它是如何使用的吗?这个演讲(Misko Hevery的“全局状态和单例”)解释了全局状态(包括单例模式)的错误以及如何避免它。你应该在那里找到你的答案。所以,一方面,你说全球国家打破了惯例