静态变量:好还是坏?

时间:2012-09-19 10:33:54

标签: java static

  

可能重复:
  Why are static variables considered evil?

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

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;
}

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

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

5 个答案:

答案 0 :(得分:17)

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

顺便说一句:我建议

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

您可以使用非静态上下文

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
    }
}

这允许您使用多个上下文创建单元测试。

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

答案 1 :(得分:7)

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

为什么事情很困难?

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

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

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

如果你把它涂成红色,那么每个人都能清楚地看到它。

此外,整个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是不可变的。那些不能改变。

答案 2 :(得分:6)

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

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

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

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

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

答案 3 :(得分:3)

坏。请参阅Cutting out Static

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

答案 4 :(得分:3)

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

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

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

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

如果你想永久存储一个值,还有其他方法,如数据库,文件等,使工作更轻松,更清洁。 我的2美分。