Skip to content

Implement efficient switch on Java enums #283

Open
@retronym

Description

@retronym

Here's what javac does:

tail -n 1000 sandbox/{E,Test}.java && javac -d . sandbox/{E,Test}.java && javap -private -c Test 'Test$1'
==> sandbox/E.java <==
public enum E {
    ZERO, ONE
}

==> sandbox/Test.java <==
public class Test {
    public static void main(String[] args) {

    }
    void enumSwitch(E e) {
        switch(e) {
            case ZERO: break;
            case ONE: break;
            default:
        }
    }
}
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: return

  void enumSwitch(E);
    Code:
       0: getstatic     #2                  // Field Test$1.$SwitchMap$E:[I
       3: aload_1
       4: invokevirtual #3                  // Method E.ordinal:()I
       7: iaload
       8: lookupswitch  { // 2
                     1: 36
                     2: 39
               default: 42
          }
      36: goto          42
      39: goto          42
      42: return
}
Compiled from "Test.java"
class Test$1 {
  static final int[] $SwitchMap$E;

  static {};
    Code:
       0: invokestatic  #1                  // Method E.values:()[LE;
       3: arraylength
       4: newarray       int
       6: putstatic     #2                  // Field $SwitchMap$E:[I
       9: getstatic     #2                  // Field $SwitchMap$E:[I
      12: getstatic     #3                  // Field E.ZERO:LE;
      15: invokevirtual #4                  // Method E.ordinal:()I
      18: iconst_1
      19: iastore
      20: goto          24
      23: astore_0
      24: getstatic     #2                  // Field $SwitchMap$E:[I
      27: getstatic     #6                  // Field E.ONE:LE;
      30: invokevirtual #4                  // Method E.ordinal:()I
      33: iconst_2
      34: iastore
      35: goto          39
      38: astore_0
      39: return
    Exception table:
       from    to  target type
           9    20    23   Class java/lang/NoSuchFieldError
          24    35    38   Class java/lang/NoSuchFieldError
}

Note the use of a synthetic static map to keep track of the mapping from enum constant to ordinal as-at the time of compilation of the match. This allows new cases to be added or cases to be reordered without a a binary incompatibility.

Be cautious not to repeat https://bugs.eclipse.org/bugs/show_bug.cgi?id=141810

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions