考虑以下代码:
public enum MyOwnEnum {
JANVIER("janvier", "3101"),
FEVRIER("février", new DateCalculator().getLeapYear()),
MARS("mars", "3103"),
AVRIL("avril", "3004");
// Two variables, the protected constructor, getters
}
代码的行为如何?该方法是在编译时直接计算并固定的,还是在有人通过FEVRIER
或MyOwnEnum.FEVRIER
调用MyOwnEnum.valueOf("FEVRIER")
时计算?还是固定的,但是在运行时?
答案 0 :(得分:4)
枚举常量在运行时或更具体地讲在类加载时创建一次。
考虑以下代码:
apt-get install build-essential
这将产生以下输出:
public enum TestEnum {
ONE("One at " + System.nanoTime()),
TWO("Two at " + System.nanoTime());
String value;
TestEnum(String value) {
System.out.println(value);
this.value = value;
}
}
public class Test {
public static void main(String[] args) throws Exception {
System.out.println("Loading");
Class.forName("TestEnum"); // Load class
System.out.println("Evaluating");
System.out.println(TestEnum.ONE.value); // Evaluate value one
System.out.println(TestEnum.TWO.value); // Evaluate value two
}
}
请注意,这些值在后续调用中不会更改。
答案 1 :(得分:2)
如果查看ENUM
生成的字节码,您会发现上面的代码与下面的代码相似:
class MyOwnEnum{
public static MyOwnEnum JANVIER = new MyOwnEnum("janvier", "3101");
public static MyOwnEnum FEVRIER = new MyOwnEnum(("février", new DateCalculator().getLeapYear()));
public static MyOwnEnum MARS = new MyOwnEnum("mars", "3103");
}
这意味着您的代码将创建DateCalculator(
的对象,并在其初始化静态变量FEVRIER 并维护静态变量的所有属性时调用getLeapYear()
。>
- 属于该类而不属于对象(实例)的静态变量
- 静态变量在执行开始时仅初始化一次。
- 将首先初始化静态变量,然后再初始化任何实例变量
- 该类的所有实例共享的单个副本
- 可以通过类名称直接访问静态变量,并且不需要任何对象。
由于FEVRIER
是静态变量public static MyOwnEnum FEVRIER = new MyOwnEnum(("février", new DateCalculator().getLeapYear()));
,因此每个类加载器加载该类后,这些代码行仅执行一次。
这是供参考的字节码:
21: ldc #26 // String FEVRIER
23: iconst_1
24: ldc #27 // String fΘvrier
26: new #29 // class com/java8/demo/DateCalculator
29: dup
30: invokespecial #31 // Method com/java8/demo/DateCalculator."<init>":()V
33: invokevirtual #33 // Method com/java8/demo/DateCalculator.getLeapYear:()Ljava/lang/String;
36: invokespecial #20 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
39: putstatic #37 // Field FEVRIER:Lcom/java8/demo/MyOwnEnum;
42: new #1 // class com/java8/demo/MyOwnEnum
45: dup
46: ldc #39 // String MARS
48: iconst_2
49: ldc #40 // String mars
51: ldc #42 // String 3103
53: invokespecial #20 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V
56: putstatic #44 // Field MARS:Lcom/java8/demo/MyOwnEnum;
59: new #1 // class com/java8/demo/MyOwnEnum