声明一个全局变量,或在每个类中多次声明

3

一个简单的问题。 在审查我的代码时,我注意到我的类或方法中有很多重复声明的变量...例如:

public Long dbInsertCheckin(final String Class) {
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
...
}

并且

public class SmashDataSource {
    final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    final SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
    final SimpleDateFormat timeFormat = new SimpleDateFormat("HHmm");
...
}

这让我想到,我可以在应用程序类中全局声明我多次使用的“dateformat”,“sdf”或“timeformat”等内容,而不是在多个地方进行声明。这样,我就可以在需要的任何地方引用它们。
public class MyApp extends Application {
public final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public final SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
    public final SimpleDateFormat timeFormat = new SimpleDateFormat("HHmm");

并在其他类中将其称为:

MyApp.dateformat
Myapp.sdf

从性能和内存使用的角度来看,这样做会更好吗?有什么理由不这样做吗?对我来说,多次声明可能会消耗更多的内存,而只需最终声明一次....但我不知道编译器如何进行优化。


你是指使用 static 而不是 final(或者实际上是 static final)吗? - zapl
5个回答

3
使用全局变量并没有什么问题。通常情况下,为了保持灵活性和封装性,应该避免使用它们。但是一些设计模式,比如工厂模式,与静态/全局类很搭配。这也避免了代码重复。
(然而,我可能会避免使用我的“Application”类,以便只在需要时使用全局字段,但这是一个实现细节。)
我可能会做这样的事情。它既保持了灵活性,又将东西放在一个地方,使得应用程序中的东西始终保持一致。
public class MyGlobals
{
    private static SimpleDateFormat dateFormat;


    public static SimpleDateFormat getDateFormat()
    {
        if(dateFormat== null)
        {
            dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
        return dateFormat;

    }
}

然后您可以在其他类中使用它:

MyGlobals.getDateFormat();

====


Here's some info from the dev docs about it:

http://developer.android.com/guide/faq/framework.html#3

For sharing complex non-persistent user-defined objects for short duration, the following approaches are recommended:

Singleton class

You can take advantage of the fact that your application components run in the same process through the use of a singleton. This is a class that is designed to have only one instance. It has a static method with a name such as getInstance() that returns the instance; the first time this method is called, it creates the global instance. Because all callers get the same instance, they can use this as a point of interaction. For example activity A may retrieve the instance and call setValue(3); later activity B may retrieve the instance and call getValue() to retrieve the last set value.

A public static field/method

An alternate way to make data accessible across Activities/Services is to use public static fields and/or methods. You can access these static fields from any other class in your application. To share an object, the activity which creates your object sets a static field to point to this object and any other activity that wants to use this object just accesses this static field.

A HashMap of WeakReferences to Objects

You can also use a HashMap of WeakReferences to Objects with Long keys. When an activity wants to pass an object to another activity, it simply puts the object in the map and sends the key (which is a unique Long based on a counter or time stamp) to the recipient activity via intent extras. The recipient activity retrieves the object using this key.

Persistent Objects

Even while an application appears to continue running, the system may choose to kill its process and restart it later. If you have data that you need to persist from one activity invocation to the next, you need to represent that data as state that gets saved by an activity when it is informed that it might go away.

For sharing complex persistent user-defined objects, the following approaches are recommended:

Application Preferences
Files
contentProviders
SQLite DB

If the shared data needs to be retained across points where the application process can be killed, then place that data in persistent storage like Application Preferences, SQLite DB, Files or ContentProviders. Please refer to the Data Storage for further details on how to use these components.


谢谢你,我最终使用Globals示例来帮助减少我的各种类中SDF的重复代码。我开始阅读Singleton的相关内容,因为我不熟悉这个术语,虽然我之前在开发者指南中读到过一些,但由于我仍在学习许多这些东西对我来说是陌生的(例如单例)。 - Evan R.

1

是的,将这些定义在一个地方是个好主意 - 不仅因为它更加清晰,而且因为这样就可以更轻松地在全局范围内更改它们,而不必浏览整个代码库。个人而言,我会选择像这样的方式:

public static final LONG_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

然而,在这种特定情况下,您需要小心,因为SimpleDateFormat对象不是线程安全的。这意味着,如果您要在整个应用程序中共享一个实例,需要采取一些额外的步骤以避免并发问题。有关更多详细信息,请参阅以下之一:

SimpleDateFormat 线程安全性

证明 SimpleDateFormat 不是线程安全的

“Java DateFormat 不是线程安全的” 这意味着什么?


1

一切都取决于您的需求和当前环境。

如果您能够承担一些重构成本,我认为最好的方法是创建一个包含所有此类变量的上下文类。您可以利用重构会话并将其他配置参数移动到该类中,并将其作为单例使用:

public class MyApplicationContext {
    //Constants and other global variables (I'd make the strings global, rather than
    //The time formats in this case.
    public final String TIME_FORMAT = "HHmm";

    //Context variables (taken from your source of choice)
    private String someConfigurationPath = "...";

    //Getters & Setters
}

1

全局变量可能是代码异味的指标。

也许可以在不同位置找到相同的简单日期格式模式。这是重构代码并将所有公共部分移动到一个单独的位置的机会,例如合并为一个新方法(如printDate(aDate)),而不是多个SimpleDateFormat实例化和进一步包围重复代码。


虽然有些晚了,但随着我对Android/Java开发越来越熟悉,我终于意识到代码的重要性。随着我的代码不断增长,我开始重构一些内容,以使其更易于阅读和跟踪,并将常见任务制作成方法,以便重复使用。非常感谢您的帮助。 - Evan R.

0

我会这样做,一切取决于将要改变的内容,但是如果您把所有配置变量都设置为静态变量,那么只需在一个地方更改日期格式,其他所有变量就不需要更改。

有时候,对于像日期格式这样的事情,最好将日期字符串放在strings.xml文件中,这样就可以根据每个国家/语言的情况来变化日期格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接