Java枚举是类。它们被编译为类。
如何编译以下示例? 什么是它的"类版本"? 什么是完全类代码?我想要实际的Java代码。
<s:property value="ABCFormBean.dependentLists[0].lastNameEng"/>
答案 0 :(得分:18)
每个enum
类都被编译为一个类java.lang.Enum
的子类。每个枚举常量在该类中变为static final
常量。然后,按照声明的顺序创建一个包含所有枚举常量的数组$VALUES
。
您可以使用命令javap -p -c Ordinals
(在已编译的.class文件中)反汇编代码以查找详细信息。
Compiled from "Ordinals.java"
public final class Ordinals extends java.lang.Enum<Ordinals> {
public static final Ordinals FIRST;
public static final Ordinals SECOND;
public static final Ordinals THIRD;
private java.lang.String notation; // your custom field
private static final Ordinals[] $VALUES; // all enum constants
public static Ordinals[] values(); // every enum class has this static method
Code:
0: getstatic #1 // Field $VALUES:[LOrdinals;
3: invokevirtual #2 // Method "[LOrdinals;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[LOrdinals;"
9: areturn
public static Ordinals valueOf(java.lang.String); // every enum class has this static method
Code:
0: ldc_w #4 // class Ordinals
3: aload_0
4: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
7: checkcast #4 // class Ordinals
10: areturn
private Ordinals(java.lang.String);
Code:
0: aload_0
1: aload_1
2: iload_2
3: invokespecial #6 // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V
6: aload_0
7: aload_3
8: putfield #7 // Field notation:Ljava/lang/String;
11: return
public java.lang.String getNotation();
Code:
0: aload_0
1: getfield #7 // Field notation:Ljava/lang/String;
4: areturn
static {}; // fills the $VALUES array and initializes the static fields corresponding to the enum constants
Code:
0: new #4 // class Ordinals
3: dup
4: ldc #8 // String FIRST
6: iconst_0
7: ldc #9 // String st
9: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
12: putstatic #11 // Field FIRST:LOrdinals;
15: new #4 // class Ordinals
18: dup
19: ldc #12 // String SECOND
21: iconst_1
22: ldc #13 // String nd
24: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
27: putstatic #14 // Field SECOND:LOrdinals;
30: new #4 // class Ordinals
33: dup
34: ldc #15 // String THIRD
36: iconst_2
37: ldc #16 // String rd
39: invokespecial #10 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
42: putstatic #17 // Field THIRD:LOrdinals;
45: iconst_3
46: anewarray #4 // class Ordinals
49: dup
50: iconst_0
51: getstatic #11 // Field FIRST:LOrdinals;
54: aastore
55: dup
56: iconst_1
57: getstatic #14 // Field SECOND:LOrdinals;
60: aastore
61: dup
62: iconst_2
63: getstatic #17 // Field THIRD:LOrdinals;
66: aastore
67: putstatic #1 // Field $VALUES:[LOrdinals;
70: return
}
这将转换为Java
public final class Ordinals extends java.lang.Enum<Ordinals> {
public static final Ordinals FIRST;
public static final Ordinals SECOND;
public static final Ordinals THIRD;
private String notation;
private static final Ordinals[] $VALUES;
public static Ordinals[] values() {
return $VALUES.clone();
}
public static Ordinals valueOf(String name) {
return (Ordinals) Enum.valueOf(Ordinals.class, name);
}
private Ordinals(String name, int ordinal, String notation) {
super(name, ordinal);
this.notation = notation
}
static {
FIRST = new Ordinals("FIRST", 0, "st");
SECOND = new Ordinals("SECOND", 1, "nd");
THIRD = new Ordinals("THIRD", 2, "rd");
Ordinals[] $VALUES = new Ordinals[3];
$VALUES[0] = FIRST;
$VALUES[1] = SECOND;
$VALUES[2] = THIRD;
Ordinals.$VALUES = $VALUES;
}
}
类版本与此完全无关 - 它取决于您使用的Java编译器的版本(或编译器上的显式设置,以强制它为较旧的Java版本进行编译)。
答案 1 :(得分:3)
您可以将枚举视为具有类型常量的类。您可以将代码视为:
public enum Ordinals {
public static final FIRST = "st";
public static final SECOND = ..;
// ...
private String notation;
private Ordinals(String notation) {
this.notation = notation;
}
public String getNotation() {
return notation;
}
}
javap
命令可能对您有用,请尝试以下操作:
javap Example.class
:
public final class Example extends java.lang.Enum<Example> {
public static final Example FIRST;
public static final Example SECOND;
public static final Example THIRD;
public static Example[] values();
public static Example valueOf(java.lang.String);
public java.lang.String getNotation();
static {};
}
答案 2 :(得分:3)
使用javap - p Ordinals.class
命令,您将获得以下代码:
public final class Ordinals extends java.lang.Enum<Ordinals> {
public static final Ordinals FIRST;
public static final Ordinals SECOND;
public static final Ordinals THIRD;
private java.lang.String notation;
private static final Ordinals[] $VALUES;
public static Ordinals[] values();
public static Ordinals valueOf(java.lang.String);
private Ordinals(java.lang.String);
public java.lang.String getNotation();
static {};
}
因此,enum
的每个值都会转换为类类型的public static final
字段。如果我理解正确,则在static
块中使用private
构造函数初始化这些字段,以便
static {
Ordinals.FIRST = new Ordinals("st");
Ordinals.SECOND = new Ordinals("nd");
Ordinals.THIRD = new Ordinals("rd");
// ...
}
正如Effective Java一书的第3项中所述,enum
或多或少与单身人士相似,这反映在上述{的使用中{ {1}}字段。
答案 3 :(得分:2)
Class version
是告诉编译类文件的Java版本的原因。你可能对此并不感兴趣。
enum
将正常编译,Ordinals
隐式扩展Enum
类,3个类级别变量,Ordinals
类的所有实例。
答案 4 :(得分:1)
javap -private
的输出是:
public final class Ordinals extends java.lang.Enum<Ordinals> {
public static final Ordinals FIRST;
public static final Ordinals SECOND;
public static final Ordinals THIRD;
private java.lang.String notation;
private static final Ordinals[] $VALUES;
public static Ordinals[] values();
public static Ordinals valueOf(java.lang.String);
private Ordinals(java.lang.String);
public java.lang.String getNotation();
static {};
}
如您所见,编译器添加了一些内容。
有一个合成数组$VALUES
,只要你调用values()
方法,它就会被复制出来。
values()
方法本身被添加到类中,以符合每个枚举的要求,即应该有一个静态values()
方法返回所有枚举常量的数组。为什么它由编译器添加而不是从Enum()
继承?因为它是静态的。
以同样的方式,添加了valueOf
。它是通过调用静态Enum.valueOf
来实现的。
在这个清单中你没有看到的一件事是构造函数有两个额外的,看不见的参数,它们在枚举常量设置时传递。它们是常数的名称及其序号。它们会从super()
传递给Enum
构造函数,并用于从中继承的方法name()
和ordinal()
。