-3

我测试了class、enum、interface这3种封装常量String的方式。

   public class Company {
        public final static String CAPITAL_ONE = "Capital_One";
    }
    public interface ICompany {
        public final static String CAPITAL_ONE = "Capital_One";
    }
    public enum ECompany {
        CAPITAL_ONE
    }

编译后,它们生成了 330 字节、181 字节和 818 字节的字节码,这意味着接口 ICompany 在加载到 jvm 时将占用更少的内存。为什么是这样?

4

2 回答 2

3

使用该javap实用程序检查 3 个“.class”文件并比较输出。例如:

$ javap -c Company.class 

简短的回答是该类必须实现一些标准方法(values(), valueOf(String), toString()enum,但其他类则不必。

话虽如此,“.class”文件的大小不一定能准确预测类已加载和 JIT 编译时使用的内存。

于 2016-07-27T15:01:32.943 回答
0

单个类文件定义一个类或接口。查看结构(https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html):

    ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
    }

一个 Enum 是一个类,如果你看看它编译成什么,你就会明白为什么会有必要的开销(参见这里:在 java 中,这种枚举类型编译成什么?)。接口是一种抽象类型,它实际上只是一个类必须遵守的一组操作和常量。

ICompany.class:

����4   
CAPITAL_ONELjava/lang/String;
ConstantValue
SourceFile
ICompany.javaICompanyjava/lang/ObjectCapital_One

ECompany.class:

����4(  


!

"
"   #$CAPITAL_ONE
LECompany;$VALUES[LECompany;values
()[LECompany;CodeLineNumberTablevalueOf(Ljava/lang/String;)LECompany;<init>(Ljava/lang/String;I)V   Signature()V<clinit>Ljava/lang/Enum<LECompany;>;
SourceFile
ECompany.java
%&ECompany'java/lang/Enumclone()Ljava/lang/Object;5(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;@1
@
    "
����    "
*���*+��7�Y��   �Y� S��

从类文件中,您可以看到示例中的接口在方法或标志方面没有太多添加,因此尺寸较小。

于 2016-07-27T15:39:30.857 回答