【问题标题】:Constructor in a class of static methods一类静态方法中的构造函数
【发布时间】:2026-02-04 20:15:02
【问题描述】:

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

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
}

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

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

【问题讨论】:

    标签: java constructor hashmap static-constructor


    【解决方案1】:

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

    static {
       populateMyMap();
    }
    

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

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

    【讨论】:

    • 这还需要将所有静态方法重写为实例方法——在我看来这是一件好事。
    【解决方案2】:

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

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

    【讨论】:

    • 是的,如果它只是简单地初始化一个值,这是最好的。
    【解决方案3】:

    使用静态初始化器:

    public class MyClass
    {
        static {
        //init
        }
    }
    

    【讨论】:

      【解决方案4】:

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

      如果运行“populateMyMap”需要花费大量时间,并且您可能不使用该功能来执行应用程序的某些功能,或者您想推迟执行 populateMyMap,则可以使用替代方法直到需要数据,以免不必要地增加启动时间。

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

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

      【讨论】: