Java 静态变量:好还是坏?

Java 静态变量:好还是坏?,java,static,Java,Static,可能重复: 我习惯在我的所有程序中广泛使用静态变量,尤其是在我使用Android时。我倾向于使用它们,因为有时通过intent发送10个或更多值会感觉非常麻烦。因此,我只是将它们声明为静态变量,并通过使用“点”操作符在其他类中轻松访问它们。使用静态变量的另一个原因是当我在整个应用程序中使用实用程序类时。就像我下面给出的代码一样,它帮助我在不同的活动中使用变量 Utility.java public class Utility { public static Facebook fb; publi

可能重复:

我习惯在我的所有程序中广泛使用静态变量,尤其是在我使用Android时。我倾向于使用它们,因为有时通过intent发送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;
}
我在网上搜索了类似的问题,发现了和,但他们似乎没有给出问题的最终答案。在大多数地方,我看到了相互矛盾的观点,因此我完全感到困惑


这是一种好的编程实践还是一种坏的编程实践?我应该使用它还是不使用它?

如果你经常使用静态变量,我完全支持静态变量,如果你将它们设置为最终变量,那么这些值永远不会改变

为什么事情会如此艰难

这就是静态变量的全部用途

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

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

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

此外,在整个程序中始终有一个实例具有相同的值。这样可以节省内存

例如

class test {
public int ten = 10;
   public test() {
   }
}
每次进行
new test()
时,都会为ten变量分配一个整数内存空间。因此,如果您有10个测试实例,那么您将有10个单独的整数,它们都持有相同的值

如果你有这个

class test {
public static int ten = 10;
   public test() {
   }
}
您有十个测试实例,您将只有一个整数实例。这样可以节省内存分配、垃圾收集。尽管我只建议对永久列表/变量进行此操作,这些列表/变量不会改变,并且可以独立地保存在内存中。不要对每个变量都这样做。对于像图像这样反复使用的大型对象,请执行此操作。在内存中多次保存同一图像是没有用的


当我最初写我的答案时,我不知道静态变量是如何工作的。我把
static final
static
搞混了。在静态变量上,可以指定新值。静态final是不可变的。这些不能更改。

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

顺便说一句:我建议

  • 将静态字段/常量与使用它们的类或包一起放置
  • 如果可能的话,将静态数组视为不可变的,使它们也成为
    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
    }
}
这允许您创建具有多个上下文的单元测试


我唯一想保留的是常量。

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

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

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

您提到的
实用程序
类基本上是此类上下文对象的一个很好的候选对象。只需将其所有字段设置为非静态,并将该类的对象交给需要它的代码即可

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

糟糕。看


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

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

如果希望长时间使用/保留某个值,则使用static可能是有益的,但是不建议将所有变量声明为static,这不是一种好做法。如果您养成了将所有值声明为静态的习惯,那么您的程序将消耗不必要的内存

除此之外,静态变量不符合OOPS概念,其中