在静态字段之前初始化的非静态字段

时间:2013-09-16 08:25:36

标签: java static initialization-order

注意:我打算将其作为一个问题发布,但我在SSCCE中重现问题的尝试使我找到了下面发布的解决方案。

我的代码中有一个类,其中privatestatic字段在 static final字段之前初始化 。我无法在以下SSCCE中重现该问题:

public class MyClass {

    private static final File myDefaultPath = 
                new File(System.getProperty("user.home"), "DefaultPath");

    private JFileChooser myFileChooser = new JFileChooser() {

        // File chooser initialization block:
        {
            myDefaultPath.mkdirs(); 
                // In my code, the above line throws:
                // java.lang.ExceptionInInitializerError
                // Caused by: java.lang.NullPointerException
                //    at init.order.MyClass$1.<init>(MyClass.java:18)
                //    at init.order.MyClass.<init>(MyClass.java:14)
                //    at init.order.MyClass.<clinit>(MyClass.java:9)
            setCurrentDirectory(myDefaultPath);
        }
    };

    public static void main (String[] args) {
        new MyClass().myFileChooser.showDialog(null, "Choose");
    }
}

由于某些原因File myDefaultPath未在JFileChooser myFileChooser之前初始化。

不应首先初始化static(尤其是static final)字段吗?

1 个答案:

答案 0 :(得分:1)

在我的代码中,我的类存储了一个static自身实例(单例),这些字段在之前在单例之后以文本方式出现的任何其他static字段时启动初始化:

public class MyClass {
    private static MyClass c = 
            new MyClass();

    private static final File myDefaultPath = 
                new File(System.getProperty("user.home"), "DefaultPath");

    private JFileChooser myFileChooser = new JFileChooser() {

        // File chooser initialization block:
        {
            myDefaultPath.mkdirs(); // This code *will* throw an exception!
            setCurrentDirectory(myDefaultPath);
        }
    };

    public static void main (String[] args) {
        c.myFileChooser.showDialog(null, "Choose");
    }
}

可能的解决方案是:

  • 在单例初始化之前移动myDefaultPath初始化。
  • myDefaultPath修改为编译时常量(并保持staticfinal修饰符),使其在{{1}的所有其他成员之前初始化(例如,使其成为硬编码的MyClass路径)。