简体   繁体   English

构造函数中的一类静态方法

[英]Constructor in a class of static methods

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! 我试过寻找答案,但我不确定要搜索什么!

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. 构造函数初始化类的实例 (当您调用new MyClass() ),但静态不属于实例,因此不应从构造函数初始化。 Initialization that you want to happen when the class is first loaded should be in a static block placed at the class level. 首次加载类时要进行的初始化应该位于类级别的static块中。

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. 考虑让您的地图成为您班级的实例成员

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

Use the static initializer: 使用静态初始化程序:

public class MyClass
{
    static {
    //init
    }
}

There are two ways of achieving this. 有两种方法可以实现这一目标。 One is to make the "populateMyMap" method a static initializer (or the approach suggested by AH). 一种是使“populateMyMap”方法成为静态初始化器(或AH建议的方法)。 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. 这通常是最好的方法,假设运行populateMyMap的成本足够小而不被注意,或者几乎每次运行应用程序时都要使用该类的功能。

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. 如果运行“populateMyMap”需要花费大量时间,或者您可能不会使用该功能执行某些应用程序,或者您希望将populateMyMap的执行推迟到数据,那么您将使用另一种方法。需要,以免不必要地增加启动时间。

If the second approach is what you want then you should switch structures and use a Singleton rather than static methods. 如果第二种方法是您想要的,那么您应该切换结构并使用Singleton而不是静态方法。 Make the methods (and data) non-static and have each user of them get the Singleton instance before calling the method on it. 使方法(和数据)非静态,并让它们的每个用户在调用方法之前获取Singleton实例。 Have "populateMyMap" called in the (private) constructor. 在(私有)构造函数中调用“populateMyMap”。 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. 这样你就不需要支付执行populateMyMap的费用,直到(或除非)你需要。

WARNING: If your data structures are not immutable, ie they can be changed after they are initialized, then you probably shouldn't be using any of these structures. 警告:如果您的数据结构不是不可变的,即它们可以在初始化后更改,那么您可能不应该使用任何这些结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM