Java枚举和其他类文件 [英] Java enum and additional class files

查看:135
本文介绍了Java枚举和其他类文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经注意到枚举在编译后引入了许多额外的类文件(Class $ 1)。它似乎附加在每一个甚至使用枚举的类上,而且这些都是复制的。

I've noticed enums introduce many additional class files (Class$1) after compilation bloating the total size. It seems to be attached to every class that even uses an enum, and these are often duplicated.

为什么会出现这种情况,有没有办法防止这种情况呢?枚举

Why does this occur and is there a way to prevent this without removing the enum.

(问题的原因是空间是我的溢价)

(Reason for question is space is at a premium for me)

编辑

在进一步调查问题时,Sun的 Javac 1.6会在每次使用Enum 上的开关时创建一个额外的合成类。它使用某种SwitchMap。 这个网站有一些更多的信息,而这里告诉你如何分析Javac正在做什么。

On investigating the issue further, Sun's Javac 1.6 creates an additional synthetic class each time you use a switch on an Enum. It uses some kind of SwitchMap. This site has some more information, and here tells you how to analyse what Javac is doing.

一个额外的物理文件似乎是每次使用枚举的开关付出的代价!

An additional physical file seems a high price to pay each time you use a switch on an enum!

有趣的是,Eclipe的编译器不会产生这些附加文件。我不知道是否唯一的解决方案是切换编译器?

Interestingly, Eclipe's compiler does not produce these additional files. I wonder if the only solution is to switch compilers?

推荐答案

我只是这个行为,这个问题出现在Googling 。我想我会分享一些我发现的额外信息。

I was just bit by this behavior and this question showed up when Googling. I thought I'd share the little bit of extra information I found out.

javac 1.5和1.6每次在枚举上使用开关时都会创建一个额外的合成类。该类包含一个所谓的切换图,它将枚举索引映射到切换表跳转号。重要的是,合成类是为交换机发生的类创建的,不是枚举类。

javac 1.5 and 1.6 create an additional synthetic class each time you use a switch on an enum. The class contains a so-called "switch map" which maps enum indices to switch table jump numbers. Importantly, the synthetic class is created for the class in which the switch occurs, not the enum class.

这是一个生成的例子:

public enum EnumClass { VALUE1, VALUE2, VALUE3 }



EnumUser.java



EnumUser.java

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";
        }
    }
}



Synthetic EnumUser $ 1.class



Synthetic EnumUser$1.class

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到[开关数量]。

This switch map is then used to generate an index for a lookupswitch or tableswitch JVM instruction. It converts each enum value into a corresponding index from 1 to [number of switch cases].

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 ,因为它执行了更有效的定时查找,而不是 lookupswitch 的线性搜索。在技​​术上来说,当使用 lookupswitch 时,javac可以使用合成切换图省略整个业务。

tableswitch is used if there are three or more switch cases as it performs a more efficient constant-time lookup vs. lookupswitch's linear search. Technically speaking javac could omit this whole business with the synthetic switch map when it uses lookupswitch.

猜测:/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /或者也许需要比原始的asker测试的更多的交换机案例,ugprades到 tableswitch

这篇关于Java枚举和其他类文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆