[英]Life span of a Java enum instance
据我所知,每个枚举类型的预定义常量只有一个实例。 那是对的吗? 现在,假设存在一个名为enum的value
的实例变量,并假设ONE
是预定义的常量。 如果value
被修改的(的)实例ONE
那么这将影响指的是所有的变量ONE
。 但是当垃圾收集器摆脱枚举的所有实例时,值的value
会发生什么? 他们甚至被扔掉了吗?
例
这是一个简单的例子,其中有两个变量A
和B
,都指的是ONE
。 在第一次使用B
之前,值的value
被否定。 如果垃圾收集器在Number B = Number.ONE;
行Number B = Number.ONE;
之前删除了ONE
的实例Number B = Number.ONE;
那么我猜想,价值的value
会被“重置”回到1。 它是否正确?
枚举:
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; }
}
主要方法:
public static void main(String[] args)
{
Number A = Number.ONE;
A.negate();
Number B = Number.ONE;
System.out.println(A + " " + B);
}
输出:
值:-1值:-1
所以我的问题是,输出是否可以如下(如果说A = null;
在使用B
之前添加)?
值:-1值:1
枚举是隐式public static final
字段,因此它们永远不会被垃圾回收。
编辑
正如@RealSkeptic在评论中所指出的那样,在具有多个类加载器的jvm实例中,事情有点复杂。 然后静态字段值可能会在卸载类时消失 。
但是,默认情况下,只要jvm实例处于活动状态,就只有一个类加载器处于活动状态,因此在您的示例应用程序中,静态字段不会被垃圾收集。
对于这个枚举:
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节。 枚举类型 :
枚举类型没有除其枚举常量定义的实例之外的实例。 尝试显式实例化枚举类型(第15.9.1节)是编译时错误。
除了编译时错误之外,还有三种机制可确保枚举类型的实例不会超出其枚举常量定义的实例:
Enum中的最终克隆方法确保永远不会克隆枚举常量。
禁止对枚举类型进行反射实例化。
序列化机制的特殊处理确保不会因反序列化而创建重复实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.