Java枚举实例的生命周期

时间:2015-07-11 11:46:54

标签: java enums

据我所知,每个枚举类型的预定义常量只有一个实例。那是对的吗?现在,假设有一个名为Recent枚举的实例变量,假设value是预定义的常量。如果为ONE的实例修改了value,则会影响引用ONE的所有变量。但是当垃圾收集器摆脱枚举的所有实例时,ONE的值会发生什么?他们甚至被扔掉了吗?

实施例

以下是一个简单示例,其中有两个变量valueA,均指B。在ONE首次使用之前,value的值被否定。如果垃圾收集器在行B之前摆脱了ONE的实例,那么我认为Number B = Number.ONE;的值将被“重置”回1。这是对的吗?

枚举:

value

主要方法:

public enum Number
{
    ONE(1), TWO(2), THREE(3); 

    int value;

    Number(int value) { this.value = value; }

    void negate() { value = -value; }

    @Override
    public String toString() { return "value: " + value; }
}

输出:

  

值:-1值:-1

所以我的问题是,输出是否可以如下(如果在使用public static void main(String[] args) { Number A = Number.ONE; A.negate(); Number B = Number.ONE; System.out.println(A + " " + B); } 之前添加了A = null;)?

  

值:-1值:1

2 个答案:

答案 0 :(得分:4)

枚举是隐式public static final字段,因此它们永远不会被垃圾收集。

修改

正如@RealSkeptic的评论中所指出的,在具有多个类加载器的jvm实例中,事情有点复杂。然后静态字段值可能会在classes are unloaded

时消失

但是,默认情况下,只要jvm实例处于活动状态,只有一个类加载器处于活动状态,因此在您的示例应用程序中,静态字段不会被垃圾收集。

答案 1 :(得分:3)

对于这个枚举:

public enum FooEnum {
  CONST
}

生成此字节代码:

Compiled from "FooEnum.java"
public final class FooEnum extends java.lang.Enum<FooEnum> {
  public static final FooEnum CONST;

  static {};
    Code:
       0: new           #1                  // class FooEnum
       3: dup
       4: ldc           #12                 // String CONST
       6: iconst_0
       7: invokespecial #13                 // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #17                 // Field CONST:LFooEnum;
      13: iconst_1
      14: anewarray     #1                  // class FooEnum
      17: dup
      18: iconst_0
      19: getstatic     #17                 // Field CONST:LFooEnum;
      22: aastore
      23: putstatic     #19                 // Field ENUM$VALUES:[LFooEnum;
      26: return

  public static FooEnum[] values();
    // elided

  public static FooEnum valueOf(java.lang.String);
    // elided
}

CONST 是一个最终的静态变量,其生命周期是该类的。

如果该类被垃圾收集,则只会对垃圾进行垃圾回收。

来自Java语言规范,Java SE 8 Edition部分8.9. Enum Types

  

枚举类型没有除其枚举常量定义的实例之外的实例。尝试显式是一个编译时错误   实例化枚举类型(§15.9.1)。

     

除了编译时错误之外,还有三种其他机制可以确保   没有枚举类型的实例存在于其定义的实例之外   枚举常量:

     

Enum中的最终克隆方法确保枚举常量永远不会   克隆。

     

禁止对枚举类型进行反射实例化。

     

序列化机制的特殊处理确保了这一点   重复实例永远不会因反序列化而创建。