As said here, switch works with the byte, short, char, and int primitive data types. It also works with enumerated types and a few special classes that “wrap” certain primitive types: Character, Byte, Short, and Integer.
The Java switch statement is compiled into the JVM bytecode tableswitch or lookupswitch. Both of these bytecodes require that the case values be unique, 32-bit, integer, compile-time constants.
The tableswitch and lookupswitch instructions both include one default branch offset and a variable-length set of case value/branch offset pairs.
Both instructions pop the key (the value of the expression in the parentheses immediately following the switch keyword) from the stack.
The key is compared with all the case values:
- If a match is found, the branch offset associated with the case value is taken.
- If no match is found, the default branch offset is taken.
Even though the above represents implementation details, I believe the types used for switch are the one compatible with an efficient bytecode for control flow, and it may have been an important part for the reason of this choice.
As said in this Java Bug:
I suppose you could allow Java switch statement cases to include other types of values, and compile a switch statement that uses one of those kinds of values into other bytecode, such as a sequence of ifs and gotos. But then we’d have to examine all switch statements carefully in order to determine if it will be compiled into a fast switch bytecode or a slow sequence of if-elses.
As said in this other Java bug
‘switch’ statements can use function-table dispatch and/or binary-tree search to match the case statements faster than just testing them one by one in order.
Scala, a language built on top of JVM, allows you to define your own case classes, that you can use in a switch statement. So, using longs or doubles or Strings in a switch statement is certainly possible.
I don’t know however how complicated and how effective is it. With simple types, the compiler just calculates an offset to jump on a table. This is definitely not the case with more complex types.
I suppose the answer has do to with the time java was designed and the goals the designers were trying to achieve. Java initial goals were to design a “better C++”, portable in many environments. I can understand why a switch on complex types didn’t fit it in.
My guess is, that long was dropped as a valid switch expression type because of/related to the fact that operations on long variables may not be atomic.