4

我有一类静态方法,可以在类中保存的地图上执行,我希望在调用类时设置地图。我试过使用私人承包商,但没有被调用。我的代码的相关部分是:

public class MyClass
{
    private static final String KEYS = "ABC";
    private static final String[] DATA = {"AAA", "BBB", "CCC"};
    private static HashMap<Character, String> myMap;

    private MyClass() {
        System.out.println("Running constructor");
        populateMyMap();
    }

    private static void populateMyMap() {
        myMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myMap.put(KEYS.charAt(i), DATA[i]);
        }
    }

    //various static methods
}

在这里使用私有构造函数是否正确,如果是,我做错了什么?

抱歉,如果这是重复的;我已经尝试搜索答案,但我不确定要搜索什么!

4

4 回答 4

8

不,私有构造函数不是您想要的。构造函数初始化类的实例(当您调用 时new MyClass()),但静态不属于实例,因此不应从构造函数初始化。您希望在首次加载类时进行的初始化应该static放在类级别的块中。

static {
   populateMyMap();
}

但是你永远不应该使用静态(全局)状态。静态状态使您的系统难以测试,它比实例状态更微妙(例如,每次加载类都有一个副本),并且通常更难以确保线程安全。

考虑让您的地图成为您的类的实例成员

于 2012-01-12T17:41:47.943 回答
5

其他几个答案中已经提到了静态初始化程序块。但实际上,我在野外更频繁地发现以下成语:

public class MyClass
{
    private static HashMap<Character, String> myMap = createMyMap();

    private static HashMap<Character, String> createMyMap() {
        HashMap<Character, String> myTmpMap = new HashMap<Character, String>();
        for (int i=0; i < KEYS.length; i++) {
            myTmpMap.put(KEYS.charAt(i), DATA[i]);
        }
        return myTmpMap;
    }
}
于 2012-01-12T17:45:40.013 回答
3

使用静态初始化器:

public class MyClass
{
    static {
    //init
    }
}
于 2012-01-12T17:41:03.260 回答
0

有两种方法可以实现这一目标。一种是使“populateMyMap”方法成为静态初始化程序(或 AH 建议的方法)。然后保证在第一次静态调用之前执行。这通常是最好的方法,假设运行 populateMyMap 的成本足够小而不会被注意到,或者如果您几乎每次运行应用程序时都将使用该类的功能。

如果运行“populateMyMap”需要花费大量时间,并且您可能不会将该功能用于应用程序的某些执行,或者您希望将 populateMyMap 的执行推迟到数据是必需的,以免不必要地增加启动时间。

如果第二种方法是您想要的,那么您应该切换结构并使用 Singleton 而不是静态方法。使方法(和数据)非静态,并让它们的每个用户在调用方法之前获取 Singleton 实例。在(私有)构造函数中调用“populateMyMap”。是的,我知道,单例的名声不好,人们总是说“避免使用它们,因为它们只是伪装的全局方法”,但静态方法也只是全局方法。你什么也没有失去。这样,您无需支付执行 populateMyMap 的费用,直到(或除非)您需要。

警告:如果您的数据结构不是不可变的,即它们可以在初始化后更改,那么您可能不应该使用这些结构中的任何一个。

于 2012-01-12T18:08:53.793 回答