Embeddable Bitcoin Miner for Websites
bitcoinplus.com5 pointsby dnadolny13 comments
class Test2{
public static void main(String[] args) {
MyEnum en = MyEnum.ONE;
switch (en) {
case ONE:
System.out.println("one"); break;
case TWO:
System.out.println("two"); break;
default:
System.out.println("default");
}
}
}
enum MyEnum {
ONE, TWO, THREE;
}
Decompiled (after being compiled with jdk1.7.0): public static void main(String args[])
{
MyEnum myenum = MyEnum.ONE;
static class _cls1
{
static final int $SwitchMap$MyEnum[];
static
{
$SwitchMap$MyEnum = new int[MyEnum.values().length];
try
{
$SwitchMap$MyEnum[MyEnum.ONE.ordinal()] = 1;
}
catch(NoSuchFieldError nosuchfielderror) { }
try
{
$SwitchMap$MyEnum[MyEnum.TWO.ordinal()] = 2;
}
catch(NoSuchFieldError nosuchfielderror1) { }
}
}
switch(_cls1.$SwitchMap$MyEnum[myenum.ordinal()])
{
case 1: // '\001'
System.out.println("one");
break;
case 2: // '\002'
System.out.println("two");
break;
default:
System.out.println("default");
break;
}
}
I wonder why it doesn't just switch on the ordinal directly. It's also worth noting that it has to make an array for MyEnum.values().length. This means if you have an enum with a lot of values, you're wasting a lot of memory (especially since it creates this array every class you use a switch in).
I tried with an enum with 40 values, and it didn't switch to a map. Maybe there's some higher threshold where it would switch to a map instead (but again, I don't understand why it wouldn't switch on ordinal() directly). String test = "asdf";
switch (test) {
case "sss":
System.out.println("sss");
break;
case "asdf":
System.out.println("asdf");
break;
}
That decompiles to: switch(test.hashCode()) {
case 114195:
if(test.equals("sss"))
byte0 = 0;
break;
case 3003444:
if(test.equals("asdf"))
byte0 = 1;
break;
}
switch(byte0) {
case 0: // '\0'
System.out.println("sss");
break;
case 1: // '\001'
System.out.println("asdf");
break;
}
So it's one switch on the String's hashcode, with calls to equals to verify that the string is a match (and an if/else if/else block if you have multiple strings in the switch that have the same hashcode), assigning the result to a temp variable, and then a switch on a temp variable to execute your code.
That was my first thought as well, but I double checked and the ordinal() method is final, so you're guaranteed not to get anything other than continuous values for your enums.
> in C compiled to x86 assembly language, a switch statement on (mostly-)contiguous values can be converted into a jump table
Ah, this is probably the intention. The JVM can probably optimize the switch. I just checked it, and when there are multiple switch statements in a class only using a few values in an enum, it tries to make them all sequential in the switch, that's why it uses the array. I guess it's just a mistake (or lazy coding) that it always makes the array size TheEnum.values().length rather than how many it's actually going to use.