【问题标题】:Static initializing block is not working as expected静态初始化块未按预期工作
【发布时间】:2021-09-21 19:26:57
【问题描述】:

我有两个类,“Test1”和“Test0”,如下代码所示。

public class Test1 {
    public static void main(String...args) {
        System.out.print(Test0.randomName);
    }
}
public class Test0 {
    public static String randomName = initRandomName();
    private static String string0;
    
    static {
        string0 = "George";
    }
    private static String initRandomName() {
        return "Mr. "+string0;
    }
}

我以为它会打印 Mr. George,但它打印了 Mr. null。 而且我不明白发生了什么。请帮助我。谢谢。

【问题讨论】:

  • randomName 的初始化之前移动string0 的分配应该可以解决它。静态变量可以有空值,randomNamestring0 被赋值之前就被访问了。

标签: java static-initializer


【解决方案1】:

JLS 12.4.2 详细说明了初始化过程。特别是:

接下来,按照文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就好像它们是一个单独的块一样。

换句话说,你可以想象你的Test0 类是这样写的:

public class Test0 {
    public static String randomName;
    private static String string0;
    
    static {
        randomName = initRandomName();
        string0 = "George";
    }

    private static String initRandomName() {
        return "Mr. " + string0;
    }
}

所以当initRandomName()被执行时,string0仍然为空。

可以randomName 字段的初始化移到静态初始化器之后,如下所示:

class Test0 {
    private static String string0;

    static {
        string0 = "George";
    }

    public static String randomName = initRandomName();

    private static String initRandomName() {
        return "Mr. "+string0;
    }
}

...但这很脆弱,依赖于没有人在不了解影响的情况下重新排序类的成员。

如果你真的需要这样的初始化,我建议声明所有字段而不初始化它们,然后在静态初始化块中初始化 everything,这样顺序就很明显了。

【讨论】:

  • 谢谢。你的回答真的很有帮助。我想知道静态初始化是如何工作的,现在我明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 2018-05-17
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多