#java #enums
#java #перечисления
Вопрос:
Я только сейчас осознаю их мощь и полезность по сравнению с использованием класса Constants… но мне очень интересно узнать, как они реализованы под капотом. Похоже, они работают во многом как статический метод или статическая константа, поскольку вы просто импортируете файл, которому «принадлежит» перечисление, и вы можете ссылаться на них с помощью enumName.valueName
. Кажется, что Javadocs онлайн предполагают, что они являются class
но кажется странным иметь «неназванный» класс по требованию. (По крайней мере, в Java …)
Ответ №1:
я считаю, что каждый экземпляр enum является анонимным конечным подклассом enum.
декомпилировать:
public enum Color {
r(0xff0000), g(0x00ff00), b(0x0000ff);
Color(int rgb) {
this.rgb=rgb;
}
final int rgb;
}
и вы можете видеть создаваемые экземпляры:
D:homeraydevindigoappsso8032067enumimplbin>javap -c Color
Compiled from "Color.java"
public final class Color extends java.lang.Enum{
public static final Color r;
public static final Color g;
public static final Color b;
final int rgb;
static {};
Code:
0: new #1; //class Color
3: dup
4: ldc #16; //String r
6: iconst_0
7: ldc #17; //int 16711680
9: invokespecial #18; //Method "<init>":(Ljava/lang/String;II)V
12: putstatic #22; //Field r:LColor;
15: new #1; //class Color
18: dup
19: ldc #24; //String g
21: iconst_1
22: ldc #25; //int 65280
24: invokespecial #18; //Method "<init>":(Ljava/lang/String;II)V
27: putstatic #26; //Field g:LColor;
30: new #1; //class Color
33: dup
34: ldc #28; //String b
36: iconst_2
37: sipush 255
40: invokespecial #18; //Method "<init>":(Ljava/lang/String;II)V
43: putstatic #29; //Field b:LColor;
46: iconst_3
47: anewarray #1; //class Color
50: dup
51: iconst_0
52: getstatic #22; //Field r:LColor;
55: aastore
56: dup
57: iconst_1
58: getstatic #26; //Field g:LColor;
61: aastore
62: dup
63: iconst_2
64: getstatic #29; //Field b:LColor;
67: aastore
68: putstatic #31; //Field ENUM$VALUES:[LColor;
71: return
public static Color[] values();
Code:
0: getstatic #31; //Field ENUM$VALUES:[LColor;
3: dup
4: astore_0
5: iconst_0
6: aload_0
7: arraylength
8: dup
9: istore_1
10: anewarray #1; //class Color
13: dup
14: astore_2
15: iconst_0
16: iload_1
17: invokestatic #43; //Method java/lang/System.arraycopy:(Ljava/lang/Obj
ect;ILjava/lang/Object;II)V
20: aload_2
21: areturn
public static Color valueOf(java.lang.String);
Code:
0: ldc #1; //class Color
2: aload_0
3: invokestatic #51; //Method java/lang/Enum.valueOf:(Ljava/lang/Class;L
java/lang/String;)Ljava/lang/Enum;
6: checkcast #1; //class Color
9: areturn
}
Комментарии:
1. Вы должны получать анонимные производные классы только в том случае, если константы перечисления имеют определения методов (пара завитушек должна делать). Как всегда, производные классы будут иметь такие имена, как
Color$0
.
Ответ №2:
Перечисления статически создаются при первой загрузке класса enum и являются неизменяемыми.
У вас должен быть конструктор в классе enum, если вы хотите присвоить своему перечислению разные значения. После завершения работы конструктора вы не можете изменить значение перечислений (неизменяемое, как сказано).
Вам не нужно использовать метод equals() для перечислений: оператор == будет работать просто отлично.
Я написал руководство в своем блоге, показывающее некоторые полезные применения класса enum, которые не являются тривиальными из простого чтения ссылки enum.
если вам интересно, вот ссылка. Блог
Комментарии:
1.
public static weekDays fromInt(int value)
Метод в вашем блоге следует заменить наEnumMap
. Там тоже есть многочисленные орфографические ошибки, как и здесь, прежде чем я исправил их для вас.2. Я не буду этого делать, но с уважением, вам нужен лучший процесс проверки, прежде чем размещать свой блог в этом случае. У вас есть элементарные ошибки, такие как ‘contractor’ для ‘constructor’, например.