- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我注意到 enums
在编译后引入了许多额外的类文件 (Class$1),使总大小膨胀。它似乎附加到每个甚至使用枚举的类,而且这些类通常是重复的。
为什么会发生这种情况,有没有办法在不删除枚举的情况下防止这种情况发生。
(问题的原因是空间对我来说非常宝贵)
编辑
在进一步调查此问题时,Sun 的 Javac 1.6 会在您每次在枚举上使用开关时创建一个额外的合成类。它使用某种 SwitchMap。 This网站有更多信息,here告诉你如何分析 Javac 在做什么。
每次在枚举上使用开关时,额外的物理文件似乎要付出高昂的代价!
有趣的是,Eclipe 的编译器不会生成这些附加文件。我想知道是否唯一的解决方案是切换编译器?
最佳答案
我只是被这种行为所困扰,在谷歌搜索时出现了这个问题。我想我会分享我发现的一点点额外信息。
每次您在枚举上使用开关时,javac 1.5 和 1.6 都会创建一个额外的合成类。该类包含一个所谓的“开关映射”,它将枚举索引映射到开关表跳转数。重要的是,合成类是为发生切换的类创建的,不是枚举类。
这是生成内容的示例:
public enum EnumClass { VALUE1, VALUE2, VALUE3 }
public class EnumUser {
public String getName(EnumClass value) {
switch (value) {
case VALUE1: return "value 1";
// No VALUE2 case.
case VALUE3: return "value 3";
default: return "other";
}
}
}
class EnumUser$1 {
static final int[] $SwitchMap$EnumClass = new int[EnumClass.values().length];
static {
$SwitchMap$EnumClass[EnumClass.VALUE1.ordinal()] = 1;
$SwitchMap$EnumClass[EnumClass.VALUE3.ordinal()] = 2;
};
}
然后使用此开关映射为 lookupswitch
或 tableswitch
JVM 指令生成索引。它将每个枚举值转换为从 1 到 [switch case 的数量] 的相应索引。
public java.lang.String getName(EnumClass);
Code:
0: getstatic #2; //Field EnumUser$1.$SwitchMap$EnumClass:[I
3: aload_1
4: invokevirtual #3; //Method EnumClass.ordinal:()I
7: iaload
8: lookupswitch{ //2
1: 36;
2: 39;
default: 42 }
36: ldc #4; //String value 1
38: areturn
39: ldc #5; //String value 3
41: areturn
42: ldc #6; //String other
44: areturn
tableswitch
在存在三个或更多 switch 情况时使用,因为与 lookupswitch
的线性搜索相比,它执行更高效的恒定时间查找。从技术上讲,当 javac 使用 lookupswitch
时,它可以通过合成开关映射省略整个业务。
推测:我手头没有 Eclipse 的编译器可以用来测试,但我想它不会为合成类烦恼,只需使用 lookupswitch
。或者它可能需要比原始提问者在“升级”到 tableswitch
之前测试的更多开关案例。
关于Java 枚举和其他类文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36844524/
我是一名优秀的程序员,十分优秀!