Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are enums internally represented in Java?

Tags:

Java enums are classes. They are compiled as classes.

How will the following example be compiled? What is its "class version"? What is the exact class code? I want actual Java code.

public enum Ordinals {     FIRST("st"),     SECOND("nd"),     THIRD("rd");     private String notation;     private Ordinals(String notation) {         this.notation = notation;     }     public String getNotation() {         return notation;     } } 
like image 440
Atom 12 Avatar asked Sep 02 '15 13:09

Atom 12


People also ask

How are enums represented in Java?

Enums are used when we know all possible values at compile-time, such as choices on a menu, rounding modes, command-line flags, etc. It is not necessary that the set of constants in an enum type stay fixed for all time. In Java (from 1.5), enums are represented using enum data type.

Can enums be defined inside method?

We can an enumeration inside a class. But, we cannot define an enum inside a method. If you try to do so it generates a compile time error saying “enum types must not be local”.

Can an enum be an inner class?

Yes, we can define an enumeration inside a class.

Can enums be defined inside static context?

Enumeration is created by using a keyword called “enum”. Given below is the syntax with which we can create an enumeration. Note: enum can be defined only inside a top-level class or interface or in a static context. It should not be inside a method.


1 Answers

Each enum class is compiled as a class being a subclass of java.lang.Enum. Each enum constant becomes a static final constant within that class. Then, an array $VALUES is created with all of the enum constants, in order of declaration.

You can disassemble the code using the command javap -p -c Ordinals (on the compiled .class file) to find out the details.

Compiled from "Ordinals.java" public final class Ordinals extends java.lang.Enum<Ordinals> {   public static final Ordinals FIRST;    public static final Ordinals SECOND;    public static final Ordinals THIRD;    private java.lang.String notation; // your custom field    private static final Ordinals[] $VALUES; // all enum constants    public static Ordinals[] values(); // every enum class has this static method     Code:        0: getstatic     #1                  // Field $VALUES:[LOrdinals;        3: invokevirtual #2                  // Method "[LOrdinals;".clone:()Ljava/lang/Object;        6: checkcast     #3                  // class "[LOrdinals;"        9: areturn           public static Ordinals valueOf(java.lang.String); // every enum class has this static method     Code:        0: ldc_w         #4                  // class Ordinals        3: aload_0               4: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;        7: checkcast     #4                  // class Ordinals       10: areturn           private Ordinals(java.lang.String);     Code:        0: aload_0               1: aload_1               2: iload_2               3: invokespecial #6                  // Method java/lang/Enum."<init>":(Ljava/lang/String;I)V        6: aload_0               7: aload_3               8: putfield      #7                  // Field notation:Ljava/lang/String;       11: return            public java.lang.String getNotation();     Code:        0: aload_0               1: getfield      #7                  // Field notation:Ljava/lang/String;        4: areturn           static {}; // fills the $VALUES array and initializes the static fields corresponding to the enum constants     Code:        0: new           #4                  // class Ordinals        3: dup                   4: ldc           #8                  // String FIRST        6: iconst_0              7: ldc           #9                  // String st        9: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V       12: putstatic     #11                 // Field FIRST:LOrdinals;       15: new           #4                  // class Ordinals       18: dup                  19: ldc           #12                 // String SECOND       21: iconst_1             22: ldc           #13                 // String nd       24: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V       27: putstatic     #14                 // Field SECOND:LOrdinals;       30: new           #4                  // class Ordinals       33: dup                  34: ldc           #15                 // String THIRD       36: iconst_2             37: ldc           #16                 // String rd       39: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V       42: putstatic     #17                 // Field THIRD:LOrdinals;       45: iconst_3             46: anewarray     #4                  // class Ordinals       49: dup                  50: iconst_0             51: getstatic     #11                 // Field FIRST:LOrdinals;       54: aastore              55: dup                  56: iconst_1             57: getstatic     #14                 // Field SECOND:LOrdinals;       60: aastore              61: dup                  62: iconst_2             63: getstatic     #17                 // Field THIRD:LOrdinals;       66: aastore              67: putstatic     #1                  // Field $VALUES:[LOrdinals;       70: return         } 

That would translate back to Java as

public final class Ordinals extends java.lang.Enum<Ordinals> {   public static final Ordinals FIRST;    public static final Ordinals SECOND;    public static final Ordinals THIRD;    private String notation;    private static final Ordinals[] $VALUES;    public static Ordinals[] values() {       return $VALUES.clone();   }    public static Ordinals valueOf(String name) {       return (Ordinals) Enum.valueOf(Ordinals.class, name);   }    private Ordinals(String name, int ordinal, String notation) {       super(name, ordinal);       this.notation = notation   }    static {       FIRST = new Ordinals("FIRST", 0, "st");       SECOND = new Ordinals("SECOND", 1, "nd");       THIRD = new Ordinals("THIRD", 2, "rd");       Ordinals[] $VALUES = new Ordinals[3];       $VALUES[0] = FIRST;       $VALUES[1] = SECOND;       $VALUES[2] = THIRD;       Ordinals.$VALUES = $VALUES;   } } 

Class version is totally unrelated to that - it depends on the version of the Java compiler that you used (or on the explicit setting on the compiler to force it to compile for an older Java version).

like image 186
Adam Michalik Avatar answered Nov 01 '22 14:11

Adam Michalik