Java 为什么静态变量被认为是邪恶的?
我是一名Java程序员,对企业界还是新手。最近,我使用Java和Java开发了一个应用程序。在我编写的代码中,使用了大量的静态数据。高级技术人员要求我减少使用静力学的数量。我在谷歌上搜索过同样的内容,我发现许多程序员相当反对使用静态变量 我发现静态变量使用起来更方便。我认为它们也很有效(如果我错了,请纠正我),因为如果我必须对一个类中的函数进行10000次调用,我会很高兴使该方法成为静态的,并在其上使用一个简单的Java 为什么静态变量被认为是邪恶的?,java,static,Java,Static,我是一名Java程序员,对企业界还是新手。最近,我使用Java和Java开发了一个应用程序。在我编写的代码中,使用了大量的静态数据。高级技术人员要求我减少使用静力学的数量。我在谷歌上搜索过同样的内容,我发现许多程序员相当反对使用静态变量 我发现静态变量使用起来更方便。我认为它们也很有效(如果我错了,请纠正我),因为如果我必须对一个类中的函数进行10000次调用,我会很高兴使该方法成为静态的,并在其上使用一个简单的类。methodCall(),而不是用10000个类实例来扰乱内存,对吗 此外,静态
类。methodCall()
,而不是用10000个类实例来扰乱内存,对吗
此外,静态减少了对代码其他部分的相互依赖。他们可以充当完美的国家持有者。除此之外,我发现静态在一些语言中得到了广泛的实现,如和。那么,为什么这种对静态的压制在程序员中很普遍(特别是在Java世界中)
PS:如果我关于静态的假设是错误的,请纠正我。静态变量代表全局状态。这很难推理,也很难测试:如果我创建一个对象的新实例,我可以在测试中推理它的新状态。如果我使用使用静态变量的代码,它可以处于任何状态,任何东西都可以修改它
我可以讲一段时间,但更大的概念是,某件事的范围越窄,就越容易推理。我们善于思考小事情,但如果没有模块化,就很难推理百万行系统的状态。顺便说一句,这适用于所有种类的事物——不仅仅是静态变量。邪恶是一个主观术语 在创建和销毁方面,您不控制静态。他们生活在程序加载和卸载的命令下 由于static存在于一个空间中,所有希望使用它们的线程都必须通过您必须管理的访问控制。这意味着程序更加耦合,这种变化更难设想和管理(如J Skeet所说)。这会导致隔离变更影响的问题,从而影响测试的管理方式
这是我遇到的两个主要问题。静态变量有两个主要问题:
- 线程安全-静态资源根据定义不是线程安全的
- 代码隐含性—您不知道何时实例化一个静态变量,也不知道它是否会在另一个静态变量之前实例化
其他答案也为避免过度使用静态提供了很好的理由。静态变量最重要的是会造成数据安全问题(任何时间更改、任何人都可以更改、无对象直接访问等) 欲了解更多信息,请阅读
谢谢。在我看来,这几乎不是性能问题,而是设计问题。我不认为静态方法的使用与静态变量的使用是错误的(但我想你实际上是在讨论方法调用)。
它只是关于如何隔离逻辑并给它一个好的位置。有时,这证明使用静态方法是合理的,
java.lang.Math
就是一个很好的例子。我认为,当您命名大多数类时,最好重新考虑您的设计。静态变量通常被认为是不好的,因为它们代表全局状态,因此更难推理。特别是,它们打破了面向对象编程的假设。在面向对象编程中,每个对象都有自己的状态,由实例(非静态)变量表示。静态变量表示实例之间的状态,这可能更难进行单元测试。这主要是因为很难将静态变量的更改隔离到单个测试中
也就是说,区分常规静态变量(通常被认为是不好的)和最终静态变量(又称常量;还不错)很重要。我发现静态变量使用起来更方便。我认为它们也很有效(如果我错了,请纠正我),因为如果我必须对一个类中的函数进行10000次调用,我会很高兴使该方法成为静态的,并在其上使用一个简单的类。methodCall()而不是用10000个类的实例扰乱内存,对吗
我明白你的想法,但是一个简单的单例模式也可以做到这一点,而不必实例化10000个对象
可以使用静态方法,但仅适用于与对象域相关且不需要或不使用对象内部属性的函数
例:
不,全球国家本身并不邪恶。但我们必须查看您的代码,看看您是否正确使用了它。很可能是一个新手滥用全球国家;就像他会滥用每一种语言特征一样 全球国家是绝对必要的。我们不能回避全球国家。我们不能避免对全球国家进行推理如果我们想理解我们的应用程序语义 那些为了摆脱全球国家而试图摆脱全球国家的人,不可避免地会以一个更加复杂的结局告终
public class WaterContainer {
private int size;
private int brand;
...etc
public static int convertToGallon(int liters)...
public static int convertToLiters(int gallon)...
}