据我所知,每个枚举类型的预定义常量只有一个实例。那是对的吗?现在,假设有一个名为Recent
枚举的实例变量,假设value
是预定义的常量。如果为ONE
的实例修改了value
,则会影响引用ONE
的所有变量。但是当垃圾收集器摆脱枚举的所有实例时,ONE
的值会发生什么?他们甚至被扔掉了吗?
实施例
以下是一个简单示例,其中有两个变量value
和A
,均指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
答案 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中的最终克隆方法确保枚举常量永远不会 克隆。
禁止对枚举类型进行反射实例化。
序列化机制的特殊处理确保了这一点 重复实例永远不会因反序列化而创建。