gpt4 book ai didi

java - 使用 values( ) 创建枚举常量的最终 Java 类数组

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:52:38 24 4
gpt4 key购买 nike

在 Java 枚举类中,我想创建一个包含该类的 values()final static 数组。当我按照以下几行执行此操作时,生成的数组为 null

public enum Name {
E1( stuff ), E2( stuff );
private static final Name[] values = Name.values();

private Name( stuff ) { more stuff; }
}

我也曾尝试通过调用显式类 setter 方法来执行此操作,但这会导致 java.lang.ExceptionInInitializerError 异常。

我知道这个问题是由一些浅层依赖引起的,因为前面代码中的 stuff 使用了其他类,这些类本身依赖于枚举类。

是否有经过测试和验证的技术来实现我的需求?

最佳答案

tl;dr:您尝试执行的操作是不可能的 - 枚举类型的静态字段在所有构造函数调用完成之前不会被初始化。


考虑这个例子:

public enum Name {
E1("hello"), E2("world");

private static final Name[] values = values();

private Name(String val) {
System.out.println("val = " + val);
dump();
}

protected void dump() {
System.out.println("this = " + this + ", values = " + values);
}
}

请注意,dump 方法存在的原因是它是一个编译时错误 (Java Language Spec section 8.9.2),试图从中引用 value 字段在 Name 的构造函数中。使用此测试工具:

public class Main {
public static void main(String... args) throws Exception {
System.out.println(Name.values());
}
}

我们得到

$ java Main
val = hello
this = E1, values = null
val = world
this = E2, values = null
[LName;@35960f05

javap反编译Name类,我们看到如下:

private static final Name[] $VALUES;

public static Name[] values();
Code:
0: getstatic #1; //Field $VALUES:[LName;
3: invokevirtual #2; //Method "[LName;".clone:()Ljava/lang/Object;
6: checkcast #3; //class "[LName;"
9: areturn

编译器创建一个私有(private)字段$VALUES保存值数组,values()方法实现为{ return (Name[])$ VALUES.clone() .那么 $VALUES 是如何初始化的呢?

static {};
Code:
0: new #4; //class Name
3: dup
4: ldc #19; //String E1
6: iconst_0
7: ldc #20; //String hello
9: invokespecial #21; //Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
12: putstatic #22; //Field E1:LName;
15: new #4; //class Name
18: dup
19: ldc #23; //String E2
21: iconst_1
22: ldc #24; //String world
24: invokespecial #21; //Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
27: putstatic #25; //Field E2:LName;
30: iconst_2
31: anewarray #4; //class Name
34: dup
35: iconst_0
36: getstatic #22; //Field E1:LName;
39: aastore
40: dup
41: iconst_1
42: getstatic #25; //Field E2:LName;
45: aastore
46: putstatic #1; //Field $VALUES:[LName;
49: invokestatic #26; //Method values:()[LName;
52: putstatic #18; //Field values:[LName;
55: return

}

我们在这里看到的是初始化基本上做了:

// compiler-generated initialization code
E1 = new Name("hello");
E2 = new Name("world");
$VALUES = new Name[] {E1, E2};

// static initializer of the values field
values = Name.values();

因此在构造函数调用的执行期间,values 字段将为 null,并且 values() 方法将抛出 NullPointerException(这将被包装在 ExceptionInInitializerError 中).

关于java - 使用 values( ) 创建枚举常量的最终 Java 类数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12447545/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com