java - 从实例初始值设定项更新静态最终字段

标签 java

Java 禁止从初始化程序访问最终静态字段。例如:

public enum Example {
    ValueA("valueAA", "valueAB"),
    ValueB("valueBA", "valueBB");

    final static Map<String, Example> exampleByPropertyA = new HashMap<>();

    final String propertyA;
    final String propertyB;

    Example(String propertyA, String propertyB) {
        this.propertyA = propertyA;
        this.propertyB = propertyB;

        Example.exampleByPropertyA.put(propertyA, this); // <- Not permitted
    }
}

但是,如果对静态 Map 的更新是在由初始化程序调用的单独方法中执行的,则没有问题。例如:

public enum Example {
    ValueA("valueAA", "valueAB"),
    ValueB("valueBA", "valueBB");

    final static Map<String, Example> exampleByPropertyA = new HashMap<>();

    final String propertyA;
    final String propertyB;

    Example(String propertyA, String propertyB) {
        this.propertyA = propertyA;
        this.propertyB = propertyB;

        addExample(this);
    }

    private addExample(Example example) {
        Example.exampleByPropertyA.put(example.propertyA, example); // <- Permitted
    }
}

鉴于此上下文,我的问题是:对成员方法的调用是否构成“卡住操作”,或者是否向 JVM 表明该对象在所有意图和目的上都已“初始化”?很好奇为什么这会有所不同。

我已经进行了一些搜索,但没有找到任何能够很好地阐明这一点的内容。

提前致谢!

最佳答案

Does a call to a member method constitute a "freeze action" or is it indicative to the JVM that the object is, for all intents and purposes, "initialized"? Curious why this makes a difference.

问题是你的类是从上到下初始化的。这意味着您的静态字段尚未初始化,即您的 map 为 null

另一种方法是添加一个静态初始化 block ,以便在所有内容初始化后调用。

static {
    for (Example e: values()) {
        addExample(e);
    }
}

private static addExample(Example example) {
    Example prev = exampleByPropertyA.put(example.propertyA, example);
    assert prev == null;
}

注意:您可以在初始化之前看到最终变量。这意味着即使不使用反射,final 也可以有前后值。

public class A {
    final String text = getText();

    private String getText() {
        System.out.println("text= " + text);
        return "is set";
    }

    public static void main(String... args) {
        new A().getText();
    }
}

打印

text= null
text= is set

使用反射,您甚至可以在初始化后更改 final 字段,但您应该避免这样做,除非没有其他选择。

关于java - 从实例初始值设定项更新静态最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49785724/

相关文章:

java - 检查单词拼写是否正确

java - 我可以使用 Swing TextField 在 Java 中进行日期数学运算吗?

java - 为什么 Ant exec 不使用我的路径?

java - 将页面重定向到另一个 url,但将 View 名称保留在地址栏中

java - Spring + JPA/Hibernate 不保存多对多映射

java - 本地类不兼容异常 : when running spark standalone from IDE

java - 将 SSLContext 设置为 org.apache.olingo.client.api.ODataClient

java - 如何实现全屏独占模式API

java - Karate :使用 JUnit5 的运行者类(class)

java - 使用 HtmlUnit 在客户端计算机上启动应用程序