我是一名Java程序员,刚进入企业界。最近我用Groovy和Java开发了一个应用程序。在我编写的所有代码中,都使用了相当多的静态元素。高级技术人员要求我减少使用的静态数据的数量。我在谷歌上搜索过相同的内容,我发现许多程序员都相当反对使用静态变量。

我发现静态变量使用起来更方便。而且我假定它们也是有效的(如果我错了请纠正我),因为如果我必须在一个类中对一个函数进行10,000次调用,我将很高兴使方法静态,并在其上使用直接的class . methodcall(),而不是用10,000个类实例使内存混乱,对吗?

此外,静态减少了对代码其他部分的相互依赖。他们可以作为完美的国家持有者。除此之外,我还发现一些语言(如Smalltalk和Scala)广泛地实现了静态。那么为什么程序员普遍反对静态(尤其是在Java世界中)呢?

PS:如果我对静态数据的假设是错误的,请纠正我。


当前回答

邪恶是一个主观的术语。

你不能从创建和破坏的角度来控制静态。他们按照程序的要求生活装卸。

由于静态对象存在于一个空间中,所有希望使用它们的线程都必须通过您必须管理的访问控制。这意味着程序更加耦合,这种变化更难想象和管理(就像J Skeet说的那样)。这导致了隔离变更影响的问题,从而影响了如何管理测试。

这是我对他们的两个主要问题。

其他回答

这里有很多很好的答案,

记忆: 静态变量只要类加载器存在(通常直到VM死亡)就存在,但这只是在大块对象/引用存储为静态的情况下。

模块化: 考虑IOC、依赖注入、代理等概念。所有这些都完全反对紧密耦合/静态实现。

其他缺点:线程安全性,可测试性

在我看来,你是在问静态变量,但你也在你的例子中指出了静态方法。

静态变量并不是邪恶的——它们被采用为全局变量,就像大多数情况下与最终修饰符结合的常量一样,但正如它所说的,不要过度使用它们。

静态方法又名实用方法。使用它们通常不是一个坏的做法,但主要的问题是它们可能阻碍测试。

作为一个伟大的java项目的例子,使用了大量的静态和做它的正确方式,请看看Play!框架。在SO中也有关于它的讨论。

与静态导入相结合的静态变量/方法也被广泛应用于方便java中声明性编程的库中,如:make it easy或Hamcrest。如果没有大量的静态变量和方法,这是不可能的。

所以静态变量(和方法)很好,但要明智地使用它们!

“静态是邪恶的”这个问题更多的是关于全局状态的问题。一个变量保持静态的适当时间是当它从来没有超过一个状态时;IE工具应该可以被整个框架访问,并且总是为相同的方法调用返回相同的结果,这些都不是静态的“邪恶”。关于你的评论:

我发现静态变量使用起来更方便。我认为他们也很有效率

对于永远不会改变的变量/类,静态是理想和有效的选择。

The problem with global state is the inherent inconsistency that it can create. Documentation about unit tests often address this issue, since any time there is a global state that can be accessed by more than multiple unrelated objects, your unit tests will be incomplete, and not 'unit' grained. As mentioned in this article about global state and singletons, if object A and B are unrelated (as in one is not expressly given reference to another), then A should not be able to affect the state of B.

在良好的代码中,有一些禁用全局状态的例外,例如时钟。时间是全局的,在某种意义上,它改变了对象的状态,而不需要编码关系。

在我看来,这与性能无关,而是与设计有关。我不认为使用静态方法和使用静态变量是错误的(但我猜你实际上是在谈论方法调用)。

它只是关于如何分离逻辑并给它一个好的位置。有时这证明使用静态方法是正确的,java.lang.Math就是一个很好的例子。我认为,当您将大多数类命名为XxxUtil或Xxxhelper时,您最好重新考虑您的设计。

我玩过很多静力学,我可以给你一个稍微不同的答案——或者可能是稍微不同的看待它的方式吗?

当我在一个类中使用静态(成员和方法)时,我最终开始注意到我的类实际上是两个分担责任的类——“静态”部分很像单例,而非静态部分(普通类)。据我所知,你可以通过为一个类选择所有静态类,为另一个类选择所有非静态类来完全分离这两个类。

当我在一个类中有一个静态集合,其中包含类的实例和一些静态方法来管理集合时,这种情况经常发生。一旦你思考一下,很明显你的类不是在做“一件事”,它是一个集合,做一些完全不同的事情。

现在,让我们稍微重构一下这个问题:如果你把你的类分成一个类,其中所有的东西都是静态的,而另一个类只是一个“普通类”,然后忘记“普通类”,那么你的问题就变成了纯静态类vs单例,这是在这里详细讨论的(可能还有其他十几个问题)。