Как enums реализованы в Java?

Я только сейчас понимаю их власть и полезность над использованием класса констант... но мне очень интересно узнать, как они реализуются под капотом. Они, похоже, работают как статический метод или статическая константа в том, что вы просто импортируете файл, который" владеет " перечислением, и вы можете ссылаться на них с помощью enumName.valueName. Javadocs онлайн, похоже, предполагают, что они class но кажется странным иметь "неназванный" класс по требованию. (По крайней мере, на Java...)

3 ответов


Я считаю, что каждый экземпляр перечисления является анонимным окончательным подклассом перечисления.

декомпилировать:

public enum Color {
    r(0xff0000), g(0x00ff00), b(0x0000ff);
    Color(int rgb) {
        this.rgb=rgb;
    }
    final int rgb;
}

и вы можете видеть, как создаются экземпляры:

D:\home\ray\dev\indigoapps\so8032067enumimpl\bin>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

}

Если вас интересует, как они реализованы под капотом, а не то, что вы можете с ними сделать, просто посмотрите на определение.

изменить 4 лет: Grr, ненадежные 4-летние ссылки... Я не нашел хорошую текущую ссылку на источник, но вы всегда можете найти ее в своем собственном источнике jdk или просто использовать wayback машина.


перечисления создаются статически при первой загрузке класса перечислений и являются неизменяемыми.

вы должны иметь конструктор в классе enum, если вы хотите назначить различные значения перечисления. После завершения конструктора вы не можете изменить значение перечислений (неизменяемое, как сказано).

вам не нужно использовать метод equals () для перечислений: оператор == будет работать нормально.

Я написал учебник в своем блоге, показывающий некоторые приятные использования класса enum, это не тривиально, просто прочитав ссылку enum.

Если вам интересно, вот ссылка. блог