Почему 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��
Из файлов классов вы можете видеть, что интерфейс в примере не так много добавлен к нему с точки зрения методов или флагов, следовательно, меньшего размера.