类中的静态方法构造函数

4

我有一个静态方法类,可以在类内部对Map进行操作,当调用该类时,我希望Map被设置好。我尝试使用私有构造函数,但它没有被调用。我的代码相关部分如下:

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个回答

8
不,你不需要私有构造函数。构造函数用于初始化类的实例(当你调用new MyClass()),但是静态状态不属于实例,因此不应该从构造函数进行初始化。你希望在类第一次加载时发生的初始化应该放在类级别的static块中。
static {
   populateMyMap();
}

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

考虑将你的地图作为你的类的一个实例成员而不是静态成员。


这也需要将所有静态方法重写为实例方法 - 在我看来这是一件好事。 - emory

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

如果只是为了初始化一个值,这绝对是首选。 - Mark Peters

3
使用静态初始化器:
public class MyClass
{
    static {
    //init
    }
}

0

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

备选方案是如果运行“populateMyMap”需要很长时间,并且您希望推迟对populateMyMap的执行,直到需要数据时才进行,以避免不必要地增加启动时间,则应该使用第二种方法。在这种情况下,您应该切换结构并使用单例而不是静态方法。使方法(和数据)非静态,在调用方法之前让每个用户获取单例实例。在(私有)构造函数中调用“populateMyMap”。是的,我知道,单例具有不良声誉,人们总是说“避免使用它们,因为它们只是伪装成全局方法”,但静态方法也只是全局方法。您没有失去任何东西。这样,您就不必支付执行populateMyMap的成本,直到(或除非)需要这样做。

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


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