如果每个枚举类型具有特定于常量的方法,为什么要为每个枚举类型创建不同的 class 文件?
Why different class files are created for each enum type if they have constant-specific method?
我有一个枚举
enum OperationsType {
ADD("+"), SUB("-"), DIV("/"), MUL("*");
private String opcodes;
private OperationsType(String opcodes) {
this.opcodes = opcodes;
}
public String toString() {
return this.opcodes;
}
}
这里所有的枚举类型都没有任何 constant Specific method
所以 javac
只为 enum
创建一个 class 文件作为
OperationsType.class
但如果我在相同代码中为所有枚举类型添加 constant Specific method
,则 javac
正在创建 5 个 class 文件。
Operations.class
Operations.class
Operations.class
Operations.class
Operations.class
以下代码
enum Operations {
ADD("+") {
public double apply(double a, double b) {
return a + b;
}
},
SUB("-") {
public double apply(double a, double b) {
return a - b;
}
},
DIV("/") {
public double apply(double a, double b) {
return a / b;
}
},
MUL("*") {
public double apply(double a, double b) {
return a * b;
}
};
private String opcodes;
private Operations(String opcodes) {
this.opcodes = opcodes;
}
public abstract double apply(double a, double b);
}
所以我怀疑为什么 compiler
为每个 enum type
创建了 4 个不同的 classes 如果他们有 constant Specific method
但没有创建不同的 classes 如果他们没有 constant Specific method
?
具有常量特定方法的枚举是使用匿名内部 classes 实现的。如The Java Language Specification所述:
The optional class body of an enum constant implicitly defines an
anonymous class declaration (§15.9.5) that extends the immediately
enclosing enum type. The class body is governed by the usual rules of
anonymous classes; in particular it cannot contain any constructors.
匿名内部 classes 是通过创建 class 文件来实现的,这些文件的名称如 OuterClass
、OuterClass
等,这正是发生在枚举。
考虑以下 class:
public class Test {
public double testApply(Operations operation, double a, double b) {
return operation.apply(a, b);
}
public static void main(String[] args) {
Test test = new Test();
assert 3.0 == test.testApply(OperationsType.ADD, 2.0, 1.0);
assert 1.0 == test.testApply(OperationsType.SUB, 2.0, 1.0);
}
}
在方法 testApply
的主体中,编译器不知道参数 operation
的确切类型(是 ADD
还是 SUB
?),它只知道是Operations
类型的实例。为了正确调度 apply
的调用,VM 需要知道参数的 运行 时间类型 。但是,如果您对所有值只有一个 class,那将是不可能的。因此,编译器为每个值创建不同的 classes 并根据 运行-time 类型调度调用。
另一方面,如果您没有定义任何常量特定方法,则无需创建子classes,因为没有必须根据 [=27= 调度的操作]接收者对象的时间类型。因此,编译器只是忽略了这些 classes.
的生成
我有一个枚举
enum OperationsType {
ADD("+"), SUB("-"), DIV("/"), MUL("*");
private String opcodes;
private OperationsType(String opcodes) {
this.opcodes = opcodes;
}
public String toString() {
return this.opcodes;
}
}
这里所有的枚举类型都没有任何 constant Specific method
所以 javac
只为 enum
创建一个 class 文件作为
OperationsType.class
但如果我在相同代码中为所有枚举类型添加 constant Specific method
,则 javac
正在创建 5 个 class 文件。
Operations.class
Operations.class
Operations.class
Operations.class
Operations.class
以下代码
enum Operations {
ADD("+") {
public double apply(double a, double b) {
return a + b;
}
},
SUB("-") {
public double apply(double a, double b) {
return a - b;
}
},
DIV("/") {
public double apply(double a, double b) {
return a / b;
}
},
MUL("*") {
public double apply(double a, double b) {
return a * b;
}
};
private String opcodes;
private Operations(String opcodes) {
this.opcodes = opcodes;
}
public abstract double apply(double a, double b);
}
所以我怀疑为什么 compiler
为每个 enum type
创建了 4 个不同的 classes 如果他们有 constant Specific method
但没有创建不同的 classes 如果他们没有 constant Specific method
?
具有常量特定方法的枚举是使用匿名内部 classes 实现的。如The Java Language Specification所述:
The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors.
匿名内部 classes 是通过创建 class 文件来实现的,这些文件的名称如 OuterClass
、OuterClass
等,这正是发生在枚举。
考虑以下 class:
public class Test {
public double testApply(Operations operation, double a, double b) {
return operation.apply(a, b);
}
public static void main(String[] args) {
Test test = new Test();
assert 3.0 == test.testApply(OperationsType.ADD, 2.0, 1.0);
assert 1.0 == test.testApply(OperationsType.SUB, 2.0, 1.0);
}
}
在方法 testApply
的主体中,编译器不知道参数 operation
的确切类型(是 ADD
还是 SUB
?),它只知道是Operations
类型的实例。为了正确调度 apply
的调用,VM 需要知道参数的 运行 时间类型 。但是,如果您对所有值只有一个 class,那将是不可能的。因此,编译器为每个值创建不同的 classes 并根据 运行-time 类型调度调用。
另一方面,如果您没有定义任何常量特定方法,则无需创建子classes,因为没有必须根据 [=27= 调度的操作]接收者对象的时间类型。因此,编译器只是忽略了这些 classes.
的生成