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

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

我想为所有要使用的类创建一个变量数组。 它将存储关键状态,因此不能设置为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 ... } 

请注意,此示例特别不是线程安全的 – 对于改进的实现方法,请参阅Java Singleton设计模式

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

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

考虑一个方法,它接受一些参数,做某事并返回一个值。

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

最常见的情况(实际上)是方法的行为将取决于对象的状态和参数,这意味着如果对象的状态已更改,则方法对具有相同(或相等)参数的多个调用的行为可能不同(可变对象)。 这不太理想,但它仍然可以轻松使用。

最不希望出现的情况是该方法取决于全局状态。 在同一(或相等)对象上使用相同(或相等)参数对同一方法进行多次调用可能会产生不同的结果。 即使该对象在调用之间处于等效状态 – 或者即使它是不可变的! 这显然非常难以使用,因为如果您怀疑某个方法没有按照预期执行的操作,则无法在任何地方测试其行为。 你必须测试它至少是因为你正在处理的情况(可能并不总是听起来那么简单)然后对于每种情况你都可以想到它会被使用并且通常会有重要的情况你会想念的。 你不能总是相信这样的方法。

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

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

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

你能告诉我一些其他(正确的)如何做到这一点的方法吗?

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

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

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

我建议想一个存储这些状态的专家。 这位专家将成为您的主要国家级别。

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

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

这是反对天真使用全球国家的论据。 这种情况有几种合法用途,但每种情况都必须根据其自身的优点加以论证。

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