首页 > 解决方案 > 有时从声明中初始化的常量返回空值。这是编码错误吗?

问题描述

空值有时由声明时初始化的常量返回。该值是否为 null 取决于其他代码的执行顺序。

我构建了一个数组,其中包含初始化为常量的对象。然后我打印数组。有时这些值都正确初始化,有时则没有,如下面的输出所示。

正确的:

[STRING, LOCAL_DATE_TIME, INTEGER]

不正确:

[STRING, null, INTEGER]

通过在打印之前添加或删除一行代码可以获得不同的结果。删除该行时会打印正确的结果。

这是包含违规行的主要课程:

package foo;
import tech.tablesaw.api.DateTimeColumn;

class DummyClass {

    public static void main(String[] args) {
        long missing = DateTimeColumn.MISSING_VALUE;
        new DummyPrinter().printColumnTypes();
    }
} 

当我在 main 中注释掉第 1 行时,代码按我的预期工作。

此外,实现打印的代码必须在一个单独的类中才能发生错误。这是那个类:

package foo;

import tech.tablesaw.api.ColumnType;
import java.util.Arrays;
import static tech.tablesaw.api.ColumnType.*;

class DummyPrinter {

    void printColumnTypes() {
        System.out.println(Arrays.toString(columnTypes));
    }

    private static final ColumnType[] columnTypes = {
        STRING,
        LOCAL_DATE_TIME,
        INTEGER,
    };
}

如您所见,数组本身是一个字面常量。

插入到数组中的值也是常量。它们在 ColumnType 接口中声明,如下所示:

DateTimeColumnType LOCAL_DATE_TIME = DateTimeColumnType.INSTANCE;

来源:[ https://github.com/jtablesaw/tablesaw/blob/master/core/src/main/java/tech/tablesaw/api/ColumnType.java ]

在该行中,值由另一个常量提供。这个是在一个名为 DateTimeColumnType 的类中声明的,它是一个单例。

这是创建 Singleton 的那个类的代码:

public static final DateTimeColumnType INSTANCE =
        new DateTimeColumnType(BYTE_SIZE, "LOCAL_DATE_TIME", "DateTime");

资料来源:[ https://github.com/jtablesaw/tablesaw/blob/master/core/src/main/java/tech/tablesaw/columns/datetimes/DateTimeColumnType.java ]

这又是一个静态的最终(常量)变量。AFAIK,它永远不应该返回null。并且使用它的接口常量永远不应该返回 null。

所以,回到打开和关闭错误的代码行。据我所知,这一行的影响是它导致类 DateTimeColumnType 在它存在时以不同的顺序加载,而不是在它不存在时加载。

我的问题是:根据 Java 语言规范,代码中是否有任何内容会导致值是否正确初始化的不确定性?换句话说,我的代码中是否存在导致问题的错误?如果是这样,是什么?或者从语言的角度来看,初始化逻辑(虽然复杂)是否正确?

标签: javastaticinitializationclassloader

解决方案


推荐阅读