When I was starting to programme in Java, the fact that switch statements didn’t take strings frustrated me. Then on using Enums, I realised the benefits that you get with them rather than passing around raw values — type safety (which brings easier refactoring) & also clarity to other developers.
I’m struggling to think of a situation where with SE7 I’ll now decide to use a switch with strings as inputs rather than Enums. If they are implemented via switching on whole strings (e.g. rather than partial or regex matches), it doesn’t seem to offer less reason for the code to change.
And with IDE tools and the read-write ratio of coding, I’d be much happier auto-generating an extra Enum than passing around string values.
What benefit do they bring to us as programmers? Less boiler-plate?
It doesn’t feel like the language was crying-out for this feature. Though maybe there’s a use-case I’m overlooking.
2
As far as I can tell, the question is why wrapping String constants into enum hasn’t been considered sufficient to cover the needs of language users. This has been addressed in the official feature proposal announced at JDK 7 (project Coin) mailing list.
Per my reading of the proposal, alternative of using enums has been dismissed on the ground that it introduces types bloat. For your convenience, relevant part of the proposal is quoted below, with the statement addressing enums quoted in bold:
MAJOR ADVANTAGE: What makes the proposal a favorable change?
More regular coding patterns can be used for operations selected on the
basis of a set of constant string values; the meaning of the new
construct should be obvious to Java developers.MAJOR BENEFIT: Why is the platform better if the proposal is adopted?
Potentially better performance for string-based dispatch code.
MAJOR DISADVANTAGE: There is always a cost.
Some increased implementation and testing complexity for the compiler.
ALTERNATIVES: Can the benefits and advantages be had some way without a
language change?No; chained if-then-else tests for string equality are potentially
expensive and introducing an enum for its switchable constants, one per
string value of interest, would add another type to a program without
good cause…
5
Apart from making the code more readable, there are potential performance gains relative to if/else if
comparisons. Whether the change is worthwhile depends on how many comparisons you would be making. A string switch will be emitted as two separate switch instructions. The first operates on hash codes, so it tends to be a lookupswitch
, ultimately yielding O(log n)
complexity. The second is always a perfect O(1)
tableswitch
, so the combined complexity is still O(log n)
. A single, linear chain of if/else if
statements would give slightly worse O(n)
complexity.
If you’re comparing more than, say, three strings, then a switch
is probably more readable and compact. It will likely perform better, though you are unlikely to notice a difference unless you are doing a large number of comparisons on a hot code path.
2
Switch for strings could be used when your enum
values come from outside, i.e. stored in a database.
Another notable thing in JDK 7 switch
is that it’s much more perfomant than if-else
constructs.
And a nice use case for speedy string switch
es could be JSON/XML stream parsing when you need to make a lot of switches on node and attribute types. I can’t think of any better option for this.
2
Simplicity
String in Switch support are useful for processing data without conversion to enum or if-else
logic. Sometimes is just easier to switch on String.
From feature proposal at JDK 7 (project Coin) mailing list (@gnat answer)
introducing an enum for its switchable constants, one per string value of interest, would add another type to a program without good cause…
If-Else version
This is short, but many if's
are hard to read. And this is slow.
if (color.equals("red")) {
System.out.println("Color is Red");
} else if (color.equals("green")) {
System.out.println("Color is Green");
} else {
System.out.println("Color not found");
}
Enum version
Enums need to be defined, this is good, but sometime not needed.
enum Color {RED, GREEN}
Processing as usual
try {
switch (Color.valueOf(color)) {
case RED:
System.out.println("Color is Red");
break;
case GREEN:
System.out.println("Color is Green");
break;
}
} catch (IllegalArgumentException e) {
System.out.println("Color not found");
}
JDK 7 – Strings in switch Statements version
We can process without converting and defining additional types.
switch (color) {
case "red":
System.out.println("Color is Red");
break;
case "green":
System.out.println("Color is Green");
break;
default:
System.out.println("Color not found");
}
1
Most improvements in any language are to make the code easier to read. I favor readable code over fancy any day.
You may not believe this but try:
public enum JettStaff {
ADRIAN("Adrian German") {
public String toString() {
return name + " ([email protected])";
}
},
ARJIT("Arjit Sengupta") {
public String toString() {
return name + " ([email protected])";
}
},
// and on for the rest...
private String name;
public JettStaff(String n) { this.name = n; }
}
JettStaff x = JettStaff.SUZANNE;
System.out.println(x);
6
Enums are great and you should use those instead of Strings when you have an ability to do so. But there are some times when you just couldn’t, for example when you need to work with some external object coming from outside of Java. Imagine that you have to parse something. Like server response, configuration, log file or something similar: you have a bunch of options that you’re looking for and there is no way those could be enums. So in Java < 7 you’d be stuck with a bunch of
if (something.equals("foo")) {
// foo processing
} else
if (something.equals("bar")) {
// bar processing
}
You can still use enums in this case by just trying to get those by names and/or by providing custom String->Enum routine but sometimes it’s not possible or just not practical (i.e. when you’d have to create too many enums)
TLDR: you absolutely should use Enums when you are working purely with Java code but it’s not always possible with external objects. I hope my explanation makes sense.
3
I don’t agree with the opinion that it’s cleaner and readable code when you use Strings
in switch statements and think that it’s a bad programming practice. If you change the value that you use to store, you have to change it every switch or if-elseif occurance. This is not good since you’re putting hardcoded values to every bir of your code. What are you going to do if one day you decide to change one of these hard coded values? Search and replace every copy of it?
If you have some hardcoded values that you do if-elseif statements, using constant primitive values for them is much better in prior to Java 1.5 just because it brings type safety.
OK, there will be situations you’ll get String values (from HTTP Request, files etc.) and converting them to the primitive values is a lof of pain. But Enum
s do a good job at this point. Because when you want to change the value you store in Enum, just change it when you declare. There is no need to change anything else in your code. (You of course need to change the values stored somewhere else).
Of couse if you’re just implementing a dirty and lazy code, it’s perfect. You don’t want to involve to code lots of Enum
s, but in a big scale complex software that’ll kill you.
If you know what information coming in and that it could only be of 5 states then use an Enum
. However if the possible states could be over 9000 and you only need to find 42, then using a switch is better because you don’t want to be typing all those states out.
An Enum tends to be the choice by most in most circumstances unless where the possible states are unknown or there are a lot and you only care about a few.
But why they introduced it now? It was just a change that allowed for cleaner code.
In 1.5 they also allowed you to create custom bodies for Enums as well.
3