Java枚举垃圾回收和枚举变量的区别

时间:2018-07-19 12:07:14

标签: java enums garbage-collection

我对Java垃圾回收和枚举类型有疑问。 可以说我有一个这样的枚举:

enum ConnectionHelper {
INSTANCE;

private boolean initialized = false;
private static int someVar;


ConnectionHelper initialize() {
    if (!initialized) {
        // Do some initialisation...
        someVar = 10;

        // NOTE: 1
        initialized = true;
    }
    return this;
}
void start() {
    // NOTE: 2
    if (!initialized) {
        throw new IllegalStateException("ConnectionHelper has to be initialized.");
    }

    // do some work...
}
  1. 现在是否存在由于垃圾回收器而初始化为FALSE的情况?我要问的原因是,如果是这种情况,我需要针对这种情况采取其他预防措施。

  2. 而且,如果我用枚举表示en单身人士,那么我使用静态还是非静态变量表示状态是否重要?例如,在此示例中,有两个变量; someVar并已初始化,如果初始化也是静态的,那么对问题1会有影响吗?还是两者都不是静态的?

    谢谢!

2 个答案:

答案 0 :(得分:3)

通常,我们可以用“否”回答各种“垃圾回收器会使程序变得奇怪”的问题。垃圾收集器的主要目的是透明地清理未使用对象的内存,而程序甚至不会注意到。产生可观察到的行为,例如从truefalse的变量翻转,绝对超出了垃圾收集器所允许的动作。

也就是说,您的程序不是线程安全的。如果多个线程在没有额外同步的情况下访问您的ConnectionHelper,它们可能会感觉到不一致的结果,包括看到false的{​​{1}}变量,而另一个线程早些时候已经看到了initialized从外部时钟的角度看待时间,或者看到true的{​​{1}},而仍然看不到为true编写的initialized的值。

解决方案很简单。不要执行多余的延迟初始化。 10常量是在类初始化期间初始化的,该类已经被JVM延迟了(如JLS §12.4.1中所指定),并由JVM使线程安全(如JLS §12.4.2中所指定)。

someVar

enum

enum ConnectionHelper {
    INSTANCE;
    private static final int someVar = 10;
    void start() {
    // do some work, use the already initialized someVar...
    }
}

是否声明变量enum ConnectionHelper { INSTANCE; private final int someVar = 10; void start() { // do some work, use the already initialized someVar... } } 都没有关系。

第一个调用enum ConnectionHelper { INSTANCE; private final int someVar; ConnectionHelper() { someVar = 10; // as place-holder for more complex initialization } void start() { // do some work, use the already initialized someVar... } } 的线程将执行类初始化,包括static的初始化。如果在初始化仍在进行时其他线程调用该方法,则它们将等待其完成。初始化完成后,所有线程都可以使用初始化后的值执行start()方法,而不会降低速度。

答案 1 :(得分:1)

枚举类型不希望进行垃圾收集。您的ConnectionHelper.INSTANCE无法取消引用,因此实例化后,该对象将始终保留在内存中。

所以,对你的问题:

AD 1:否,无法还原。将其重新设置为false的唯一方法是手动设置。

AD 2:单身没有差异。如果您有更多实例,将会有所不同,因为它们将共享static变量,而不是通常的变量。