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

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

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

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


当前回答

静态变量表示全局状态。这很难推理,也很难测试:如果我创建了一个对象的新实例,我就可以在测试中推理它的新状态。如果我使用使用静态变量的代码,它可以处于任何状态-任何东西都可以修改它。

我还可以继续讲很久,但更重要的概念是,事物的范围越窄,就越容易进行推理。我们擅长思考小事,但如果没有模块化,就很难推断出百万行系统的状态。顺便说一下,这适用于各种各样的东西——不仅仅是静态变量。

其他回答

有人可能会建议,在使用静态变量的大多数情况下,您确实希望使用单例模式。

全局状态的问题在于,有时在简单的上下文中作为全局是有意义的,但在实际的上下文中需要更加灵活,这就是单例模式变得有用的地方。

从我的观点来看,静态变量应该只读取数据或变量创建的约定。

For example we have a ui of some project, and we have a list of countries, languages, user roles, etc. And we have class to organize this data. we absolutely sure that app will not work without this lists. so the first that we do on app init is checking this list for updates and getting this list from api (if needed). So we agree that this data is "always" present in app. It is practically read only data so we don't need to take care of it's state - thinking about this case we really don't want to have a lot of instances of those data - this case looks a perfect candidate to be static.

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

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

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

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

静态变量没有好坏之分。它们表示描述整个类而不是特定实例的属性。如果需要为某个类的所有实例设置一个计数器,则静态变量将是保存该值的合适位置。

当您尝试使用静态变量来保存与实例相关的值时,就会出现问题。

总结在Java中使用静态方法的几个基本优点和缺点:

优点:

全局可访问,即不与任何特定的对象实例绑定。 每个JVM一个实例。 可以通过类名访问(不需要对象)。 包含一个适用于所有实例的值。 在JVM启动时加载,并在JVM关闭时死亡。 它们不会修改Object的状态。

缺点:

Static members are always part of memory whether they are in use or not. You can not control creation and destruction of static variable. Usefully they have been created at program loading and destroyed when program unload (or when JVM shuts down). You can make statics thread safe using synchronize but you need some extra efforts. If one thread change value of a static variable that can possibly break functionality of other threads. You must know “static“ before using it. You cannot override static methods. Serialization doesn't work well with them. They don't participate in runtime polymorphism. There is a memory issue (to some extent but not much I guess) if a large number of static variables/methods are used. Because they will not be Garbage Collected until program ends. Static methods are hard to test too.