19

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

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

实用程序.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;
}

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

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

4

5 回答 5

18

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

顺便说一句:我建议

  • 将静态字段/常量与使用它们的类或包一起放置
  • 如果可能的话,将静态数组视为不可变的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
    }
}

这允许您创建具有多个上下文的单元测试。

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

于 2012-09-19T10:39:32.950 回答
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 是不可变的。那些不能改变。

于 2012-09-19T10:37:19.903 回答
7

这种编程实践在纯面向对象的语言(如 Java)中是不好的,因为它破坏了面向对象的编程范式。它们可以工作,但是一旦你意识到你确实需要它们的多个版本,你将需要大量的重构来实现这一点。

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

下一点:测试。如果您需要用代理或其他测试内容替换一些静态字段以进行单元测试,那您基本上就完蛋了。使用上下文对象,您可以简单地将不同的上下文对象传递给单元测试。

您提到的Utility类基本上是此类上下文对象的良好候选者。只需将其所有字段设为非静态并将该类的对象交给需要它的代码即可。

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

于 2012-09-19T10:41:46.910 回答
3

坏的。请参阅消除静态

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

于 2012-09-19T10:42:16.310 回答
3

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

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

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

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

如果你想永久存储一个值,还有其他方法,比如数据库、文件等,可以让工作更轻松、更干净。只是我的2美分。

于 2012-09-19T10:44:12.803 回答