Why can't I use switch statement on a String?
Switch statements with String
cases have been implemented in Java SE 7, at least 16 years after they were first requested. A clear reason for the delay was not provided, but it likely had to do with performance.
Implementation in JDK 7
The feature has now been implemented in javac
with a "de-sugaring" process; a clean, high-level syntax using String
constants in case
declarations is expanded at compile-time into more complex code following a pattern. The resulting code uses JVM instructions that have always existed.
A switch
with String
cases is translated into two switches during compilation. The first maps each string to a unique integer—its position in the original switch. This is done by first switching on the hash code of the label. The corresponding case is an if
statement that tests string equality; if there are collisions on the hash, the test is a cascading if-else-if
. The second switch mirrors that in the original source code, but substitutes the case labels with their corresponding positions. This two-step process makes it easy to preserve the flow control of the original switch.
Switches in the JVM
For more technical depth on switch
, you can refer to the JVM Specification, where the compilation of switch statements is described. In a nutshell, there are two different JVM instructions that can be used for a switch, depending on the sparsity of the constants used by the cases. Both depend on using integer constants for each case to execute efficiently.
If the constants are dense, they are used as an index (after subtracting the lowest value) into a table of instruction pointers—the tableswitch
instruction.
If the constants are sparse, a binary search for the correct case is performed—the lookupswitch
instruction.
In de-sugaring a switch
on String
objects, both instructions are likely to be used. The lookupswitch
is suitable for the first switch on hash codes to find the original position of the case. The resulting ordinal is a natural fit for a tableswitch
.
Both instructions require the integer constants assigned to each case to be sorted at compile time. At runtime, while the O(1)
performance of tableswitch
generally appears better than the O(log(n))
performance of lookupswitch
, it requires some analysis to determine whether the table is dense enough to justify the space–time tradeoff. Bill Venners wrote a great article that covers this in more detail, along with an under-the-hood look at other Java flow control instructions.
Before JDK 7
Prior to JDK 7, enum
could approximate a String
-based switch. This uses the static valueOf
method generated by the compiler on every enum
type. For example:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
Why can't I use switch statement on a String?
Switch statements with String
cases have been implemented in Java SE 7, at least 16 years after they were first requested. A clear reason for the delay was not provided, but it likely had to do with performance.
Implementation in JDK 7
The feature has now been implemented in javac
with a "de-sugaring" process; a clean, high-level syntax using String
constants in case
declarations is expanded at compile-time into more complex code following a pattern. The resulting code uses JVM instructions that have always existed.
A switch
with String
cases is translated into two switches during compilation. The first maps each string to a unique integer—its position in the original switch. This is done by first switching on the hash code of the label. The corresponding case is an if
statement that tests string equality; if there are collisions on the hash, the test is a cascading if-else-if
. The second switch mirrors that in the original source code, but substitutes the case labels with their corresponding positions. This two-step process makes it easy to preserve the flow control of the original switch.
Switches in the JVM
For more technical depth on switch
, you can refer to the JVM Specification, where the compilation of switch statements is described. In a nutshell, there are two different JVM instructions that can be used for a switch, depending on the sparsity of the constants used by the cases. Both depend on using integer constants for each case to execute efficiently.
If the constants are dense, they are used as an index (after subtracting the lowest value) into a table of instruction pointers—the tableswitch
instruction.
If the constants are sparse, a binary search for the correct case is performed—the lookupswitch
instruction.
In de-sugaring a switch
on String
objects, both instructions are likely to be used. The lookupswitch
is suitable for the first switch on hash codes to find the original position of the case. The resulting ordinal is a natural fit for a tableswitch
.
Both instructions require the integer constants assigned to each case to be sorted at compile time. At runtime, while the O(1)
performance of tableswitch
generally appears better than the O(log(n))
performance of lookupswitch
, it requires some analysis to determine whether the table is dense enough to justify the space–time tradeoff. Bill Venners wrote a great article that covers this in more detail, along with an under-the-hood look at other Java flow control instructions.
Before JDK 7
Prior to JDK 7, enum
could approximate a String
-based switch. This uses the static valueOf
method generated by the compiler on every enum
type. For example:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
can we use switch-case statement with strings in c?
No, you can't. Switch is intended to compare numeric types, and for extension char types.
Instead you should use the strcmp function, included in string header:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
if (argc != 4) {
puts("Incorrect usage");
return 1;
}
/* You should check the number of arguments */
char * op = argv[1];
int a = atoi(argv[2]);
int b = atoi(argv[3]);
/* You should check correct input too */
if (strcmp(op, "+") == 0)
printf("%d + %d = %d\n", a, b, a + b);
else if (strcmp(op, "-") == 0)
printf("%d - %d = %d\n", a, b, a - b);
/* Add more functions here */
return 0;
}
Why can't the switch statement be applied on strings?
The reason why has to do with the type system. C/C++ doesn't really support strings as a type. It does support the idea of a constant char array but it doesn't really fully understand the notion of a string.
In order to generate the code for a switch statement the compiler must understand what it means for two values to be equal. For items like ints and enums, this is a trivial bit comparison. But how should the compiler compare 2 string values? Case sensitive, insensitive, culture aware, etc ... Without a full awareness of a string this cannot be accurately answered.
Additionally, C/C++ switch statements are typically generated as branch tables. It's not nearly as easy to generate a branch table for a string style switch.
jdk 8 does not allow string in switch statement ?? why
Cannot switch on a value of type String for source level below 1.7
You aren't using jdk 8. You either need to update java or fix the compiler compliance level of your IDE.
To change compiler compliance level in Eclipse:
Open Window > Preferences > Java > Compiler
Change the Compiler compliance level under "JDK Compliance" to 1.8
To change the source level in Netbeans:
Right-click the Libraries node in the Project view and choose Properties.
Choose "Sources" and set the Source Level to 1.8
To change the project bytecode version in IntelliJ IDEA:
Open File > Settings > Build, Execution, Deployment > Compiler > Java Compiler
Set the Project bytecode version to 1.8
Why doesn't String switch statement support a null case?
As damryfbfnetsi points out in the comments, JLS §14.11 has the following note:
The prohibition against using
null
as a switch label prevents one from writing code that can never be executed. If theswitch
expression is of a reference type, that is,String
or a boxed primitive type or an enum type, then a run-time error will occur if the expression evaluates tonull
at run time. In the judgment of the designers of the Java programming language, this is a better outcome than silently skipping the entireswitch
statement or choosing to execute the statements (if any) after thedefault
label (if any).
(emphasis mine)
While the last sentence skips over the possibility of using case null:
, it seems reasonable and offers a view into the language designers' intentions.
If we rather look at implementation details, this blog post by Christian Hujer has some insightful speculation about why null
isn't allowed in switches (although it centers on the enum
switch rather than the String
switch):
Under the hood, the
switch
statement will typically compile to a tablesswitch byte code. And the "physical" argument toswitch
as well as its cases areint
s. The int value to switch on is determined by invoking the methodEnum.ordinal()
. The [...] ordinals start at zero.That means, mapping
null
to0
wouldn't be a good idea. A switch on the first enum value would be indistinguishible from null. Maybe it would've been a good idea to start counting the ordinals for enums at 1. However it hasn't been defined like that, and this definition can not be changed.
While String
switches are implemented differently, the enum
switch came first and set the precedent for how switching on a reference type should behave when the reference is null
.
Related Topics
Java Refuses to Start - Could Not Reserve Enough Space For Object Heap
Why Maven Uses Jdk 1.6 But My Java -Version Is 1.7
How to Avoid Arrayindexoutofboundsexception or Indexoutofboundsexception
Is Java "Pass-By-Reference" or "Pass-By-Value"
The Use of Multiple Jframes: Good or Bad Practice
Should I Avoid the Use of Set(Preferred|Maximum|Minimum)Size Methods in Java Swing
Providing White Space in a Swing Gui
What Is Pecs (Producer Extends Consumer Super)
How to Fix Java.Lang.Unsupportedclassversionerror: Unsupported Major.Minor Version
Including All the Jars in a Directory Within the Java Classpath
Cannot Make a Static Reference to the Non-Static Method
How to Render a Pdf File in Android
Retain Precision With Double in Java