静态变量:好还是坏?

可能重复:
为什么静态变量被视为邪恶?

我习惯在我的所有程序中广泛使用静态变量 ,特别是在我使用Android时。 我倾向于使用它们,因为有时通过Intents发送10个或更多值会感觉非常麻烦 。 因此,我只是将它们声明为静态变量,并使用“点”运算符轻松地在其他类中访问它们。 使用静态变量的另一个原因是我在整个应用程序中使用Utility类 。 就像我下面给出的代码一样,可以帮助我在不同的活动中使用变量

Utility.java

public class Utility { public static Facebook fb; public static AsyncFacebookRunner fbAsyncRunner; public static String[] fbPermissions = {"email", "read_stream", "user_birthday"}; public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile"; public static SharedPreferences prefs; public static Editor editor; public static String access_token; public static long expires; } 

我在网上搜索了类似的问题并遇到了这个和这个 ,但他们似乎没有给出问题的最终答案。 在大多数地方,我看到了相互矛盾的观点,因此我完全感到困惑。

这是一个好的编程习惯还是坏的? 我应该使用它吗?

您可以使用“上下文”对象替换所有静态字段,您可以传递该对象或创建单例。 可以删除几乎所有的静态字段。 这是否是一个好主意取决于你,但我不认为使用实例字段要困难得多。

顺便说一句:我建议

  • 将静态字段/常量放在使用它们的类或包中
  • 将静态数组视为不可变的,如果可能的话也将它们作为final

您可以使用非静态Context

 public class Context { public static final String PREF_UTILITY_FILE_NAME = "PrefUtilityFile"; public Facebook fb; public AsyncFacebookRunner fbAsyncRunner; public String[] fbPermissions = {"email", "read_stream", "user_birthday"}; public SharedPreferences prefs; public Editor editor; public String access_token; public long expires; } // pass to constructor as required class UsesContext { final Context context; public UsesContext(Context context) { this.context = context; } public void method() { // can use context } } 

这允许您使用多个上下文创建unit testing。

我唯一会留下静态的是常量。

这种编程实践在纯面向对象语言(如Java)中很糟糕,因为它破坏了面向对象的编程范例。 它们有效,但是一旦你意识到你需要不止一个版本,你就需要进行大量的重构才能实现。

如果您认为通过方法调用处理太多参数很麻烦。 只需创建一个包含所有这些对象的对象(参见Peter Lawrey的回答,“Context”对象)并仅传递此对象。 然后,您可以再次在该对象上使用“简单点符号”。

下一点:测试。 如果你需要用代理或其他测试东西替换一些静态字段进行unit testing,你基本上就搞砸了。 使用上下文对象,您可以简单地将不同的上下文对象放入unit testing中。

您提到的Utility类基本上是这种上下文对象的良好候选者。 只需使其所有字段都是非静态的,并将该类的对象交给需要它的代码。

我可以告诉你一个关于我使用静力学搞砸的例子:我曾经写过一个编译器。 因为我认为在编译运行期间,有许多上下文只需要一次(例如符号表),我将它们全部添加为静态变量。 后来我决定允许multithreading编译和“服务器”模式,其中编译器一直在空闲模式下运行,直到客户端发送编译请求(这节省了Java的长启动时间)。 现在我被搞砸了。 现在有多个并发上下文(并发编译器线程),但所有上下文都是通过静态变量共享的。 我需要大约一周的时间来通过上下文对象替换所有静态并引入了大量的错误。

如果你经常使用静态变量,我就是静态变量,如果你把它们作为最终值,那么值永远不会改变。

为什么事情困难?

这就是静态变量的全部内容。

基本上他们所做的是提供一个通用的访问点,您可以从任何上下文(静态,程序流,外部)访问。

你基本上说前门在这里,它是黄色的。 从外面偷看的人会看到黄色的门。 在里面走路的人会看到门,它是黄色的。 一个房间里的某个人可以看到走廊,看到它是黄色的。

如果你把它漆成红色,每个人都会清楚地看到它。

此外,整个ENTIRE程序中总会有1个实例具有相同的值。 这节省了记忆。

举个例子

 class test { public int ten = 10; public test() { } } 

每次进行new test() ,都会为十个变量分配一个整数存储空间。 因此,如果你有10个测试实例,你将拥有10个单独的整数,它们都拥有相同的值。

如果你有这个

 class test { public static int ten = 10; public test() { } } 

并且您有十个测试实例,您将只有一个整数实例十。 这节省了内存分配,垃圾收集。 虽然我只建议这个持久列表/变量不会改变,你可以负担得起保持在内存中。 不要对每个变量都这样做。 为大型事物执行此操作,例如您可以反复使用的图像。 无需多次在内存中保留相同的图像。

当我最初写我的答案时,我不知道静态变量是如何工作的。 我得到static finalstatic混合。 在静态变量上,您可以分配新值。 static final是不可变的。 那些不能改变。

声明为static的变量将保留在内存中,直到程序执行,从而占用额外的空间。

如果要长时间使用/保留值,静态的使用可能是有益的,但是不推荐将所有变量声明为静态,这不是一个好习惯。 如果你养成了将所有值声明为静态的习惯,那么程序会占用不必要的内存。

除此之外,静态变量不符合OOPS概念,其中范围,抽象和封装与泡腾对象一起定义。 通过它您可以随意调用和删除变量。

如果您在有限的内存空间(例如移动应用程序)中工作,则会出现使用静态变量的最大缺点,如果它被变量和较少的内存空间占用,应用程序将崩溃。

如果你想永久存储一个值,还有其他方法,如数据库,文件等,使工作更容易和更清洁。 只需2美分。

坏。 请参阅切割静电 。

在我看来,静态变量包含一个或多个对象,但是这些对象是格式错误的:没有在类中组织(没有类型层次结构),错误的封装,仅限于单个实例(这可能在将来导致麻烦,需要多个实例) 。