Constructor in a class of static methods

倖福魔咒の 提交于 2019-12-12 12:12:01

问题


I've got a class of static methods that can be performed on a map held within the class, and I want the map to be set up when the class is called. I've tried using a private contructor, but it isn't being called. The relevant parts of my code are:

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
}

Is a private constructor the right thing to be using here, and if so what am I doing wrong?

Sorry if this is a duplicate; I've tried searching for answers, but I'm not sure what to search for!


回答1:


The static initializer block has been mentioned in several other answers. But practically I find the following idiom more frequently in the wild:

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



回答2:


No, a private constructor is not what you want. A constructor initializes an instance of your class (when you call new MyClass()) , but static state does not belong to an instance and so shouldn't be initialized from the constructor. Initialization that you want to happen when the class is first loaded should be in a static block placed at the class level.

static {
   populateMyMap();
}

But you should never be using static (global) state. Static state makes your system prohibitively difficult to test, it is more nuanced than instance state (for example, you have one copy per load of the class) and it is typically harder to make thread safe.

Consider making your map an instance member of your class instead.




回答3:


Use the static initializer:

public class MyClass
{
    static {
    //init
    }
}



回答4:


There are two ways of achieving this. One is to make the "populateMyMap" method a static initializer (or the approach suggested by A.H.). Then it is guaranteed to be executed before the first static call. This is usually the best way, assuming that either the cost of running populateMyMap is small enough not to be noticed, or if you are going to use the functionality of the class nearly every time the application is run.

The alternative approach is what you would use if running "populateMyMap" is something that takes a significant amount of time AND either you either might not use the functionality for some executions of the app, or you want to defer the execution of populateMyMap until the data is needed, so as not to unnecessarily increase startup time.

If the second approach is what you want then you should switch structures and use a Singleton rather than static methods. Make the methods (and data) non-static and have each user of them get the Singleton instance before calling the method on it. Have "populateMyMap" called in the (private) constructor. Yes I know, Singletons have a bad reputation and people always say "avoid them because they are just global methods in disguise", but static methods are also just global methods. You're losing nothing. And this way you don't pay the cost of executing populateMyMap until (or unless) you need to.

WARNING: If your data structures are not immutable, i.e they can be changed after they are initialized, then you probably shouldn't be using any of these structures.



来源:https://stackoverflow.com/questions/8839625/constructor-in-a-class-of-static-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!