Как реализованы перечисления в Java?

#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’, например.