Почему Java Enums использует больше памяти, чем интерфейсы?

Я протестировал класс, enum, интерфейс этих трех способов инкапсуляции константы 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. Почему это?

2 ответа

Решение

Использовать javap Утилита для изучения 3 ".class" файлов и сравнения результатов. Например:

$ javap -c Company.class 

Короткий ответ: есть несколько стандартных методов (values(), valueOf(String), toString()) что enum Класс должен реализовывать, но другие классы не должны.

Сказав это, размер файла ".class" не обязательно является точным предиктором памяти, используемой, когда класс загружен и JIT скомпилирован.

Один файл класса определяет класс или интерфейс. Рассмотрим структуру ( 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, для чего компилируется такой тип enum?). Интерфейс - это абстрактный тип, который на самом деле представляет собой набор операций и констант, которым должен соответствовать класс.

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��

Из файлов классов вы можете видеть, что интерфейс в примере не так много добавлен к нему с точки зрения методов или флагов, следовательно, меньшего размера.

Другие вопросы по тегам