While using Java's switch case, it excepts only char and int, but I want to provide string cases. How to make this possible?
switch-case
is a language construct that is designed to accept only integral values. You cannot change the way it works.
You cannot have strings in a switch-case (yet). It's on its way in Java 7.
The current types that it accepts include char
, byte
, short
, int
, Character
, Byte
, Short
, Integer
, or an enum type.
From the Java Language Specification:
The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (§8.9), or a compile-time error occurs.
...
All of the following must be true, or a compile-time error will result:
- Every case constant expression associated with a switch statement must be assignable (§5.2) to the type of the switch Expression.
- No switch label is null.
- No two of the case constant expressions associated with a switch statement may have the same value.
- At most one default label may be associated with the same switch statement.
As other replies have stated, Java (currently) does not support switching on String values. There are three commonly used approaches for achieving the same effect:
Replace the
switch
with a chain ofif ... else if ...
statements. (Yuck).Create and populate a HashMap that maps the strings to integer codes and then switch on the codes.
Define an
enum
type whose values have names that are the same as the Strings, use EType.valueOf(String) to map the strings to enum values, and switch on the enum values. (It may be more complicated if you are required to obey the Java identifier style rules for the enum values, or if the strings contain non-identifier characters.)@Pete Kirkham adds the "classic hack" of switching on the hashcode of the String. However, there are a couple of problems with that:
It doesn't correctly deal with the case where the supplied string is not one of the required strings. (Think: many strings hash to the same hashcode.)
The hashcodes will most likely be widely spaced, so the JIT compiler will have to compile the switch as a sequence of test / branches based on the hashcode values. That is faster than test / branches based on
String.equals()
, but it isO(N)
... versusO(1)
for a switch that compiles to a jump table.
I you're really desperate you could switch on the String's digest. If you're into that sort of thing that is.
import java.util.zip.Adler32;
public class StringSwitch {
public static void main(String[] args) {
String arg;
if (args == null || args.length == 0) {
arg = "stackoverflow";
} else {
arg = args[0];
}
Adler32 algorithm = new Adler32();
algorithm.update(arg.getBytes());
int hash = (int) algorithm.getValue();
switch (hash) {
case 647693707:
System.out.println("Programming Q & A");
break;
case 145556093:
System.out.println("Narwhals and bacon");
break;
case 193790704:
System.out.println("How do they work?");
break;
}
}
}
What can I switch on?
As of Java 6, you can only switch on the following types:
JLS 14.11 The
switch
statementSwitchStatement: switch ( Expression ) SwitchBlock
The type of the
Expression
must bechar
,byte
,short
,int
,Character
,Byte
,Short
,Integer
, or anenum
type, or a compile-time error occurs. [...] Everycase
constant expression associated with a switch statement must be assignable to the type of theswitch Expression
.
So what can I do?
Depending on your use case, you may be able to use enum
instead of String
. Unlike String
, you can switch on an enum
. Here's an example:
public class EnumSwitchSample {
static enum Color {
BLACK, WHITE;
}
public static void main(String[] args) {
test(Color.valueOf("BLACK"));
// "It's black!"
test(Color.WHITE);
// "It's white!"
}
static void test(Color c) {
switch (c) {
case BLACK:
System.out.println("It's black!");
break;
case WHITE:
System.out.println("It's white!");
break;
}
}
}
However, enum
in Java is actually quite powerful, and you may not even need to switch
on it. Here's an example:
public class EnumMemberExample {
static enum Mood {
SCREAM("I'M LOUD AND OBNOXIOUS!!!") {
@Override public String say(String statement) {
return statement.toUpperCase().replaceAll("!", "!!!");
}
},
WHISPER("Ssh... Be vewy vewy quiet...") {
@Override public String say(String statement) {
return statement.toLowerCase().replaceAll("!", "...");
}
};
final String msg;
Mood(String msg) { this.msg = msg; }
String getMessage() { return msg; }
abstract String say(String statement);
}
public static void main(String[] args) {
test(Mood.SCREAM);
// "I'M LOUD AND OBNOXIOUS!!!"
// "HELLO!!! HOW ARE YOU!!!"
test(Mood.WHISPER);
// "Ssh... Be vewy vewy quiet..."
// "hello... how are you..."
}
static void test(Mood m) {
System.out.println(m.getMessage());
System.out.println(m.say("Hello! How are you!"));
}
}
See also
Related questions
Let me put my dogmatic hat on (and you're coding in Java so I'm assuming you care about OOP)
Rather than asking: how do I do the wrong thing? instead ask: what is the right thing to do? In this case: http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html and for some discussion: http://www.c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism