It's time to "switch" on Java
Anyone who has used a switch statement should be familiar with this in Java.
private String getName(String input) {
switch (input) {
case "a":
return "A";
case "b":
return "B";
case "c":
return "C";
default:
return "D";
}
}
Looks pretty straight forward at a glance, but is it really? What if I use enums instead?
public enum InputTypes {
A, B, C;
}
Now the code would look like the following:
private String getName(InputTypes input) {
switch (input) {
case A:
return "A";
case B:
return "B";
case C:
return "C";
default:
return "D";
}
}
But for any eager eye, it should be obvious that there is something fishy here: in the enum, I have exhausted all the options in that enum, why should there be a default in the implementation, shouldn't the compiler be happy with all the explicit cases listed already?
The answer is simple, yet, somehow surprising:
private String getName(InputTypes input) {
switch (input) {
case A:
return "A";
case B:
return "B";
case C:
return "C";
}
}
This implementation would upset the compiler because it thinks there is a "missing return statement" error. And as a matter of fact, it appears that the compiler does not even bother checking whether all the possible cases have been covered, and a terrible way to fix this issue was either to add a default or throwing an exception.
private String getName(InputTypes input) throws Exception {
switch (input) {
case A:
return "A";
case B:
return "B";
case C:
return "C";
}
throw new Exception("duh");
}
This fix actually makes the code rather unreasonable and unpleasant to read. And I wonder why the switch statement is not any cleverer, what makes it so different from switch expression used for pattern matching in Scala.
In fact, that's the knack of it, I've been trying to use switch statement in Java like the way I would do with switch expression in Scala, and this has caught some Java experts by surprise as well.
Following that train of thought, if I were to implement switch statement properly, it would have been alright, even though it seems like just another way to stick a default value.
private String getName(InputTypes input) {
String result = "";
switch (input) {
case A:
result = "A";
break;
case B:
result = "B";
break;
case C:
result = "C";
break;
}
return result;
}
Luckily, life could have made easier with switch expression introduced in Java 14.
private String getName(InputTypes input) {
return switch (input) {
case A -> "A";
case B -> "B";
case C -> "C";
};
}
Smells nice, doesn't it?
There are a few catches worth mentioning as well:
The cases of a switch expression must be exhausted
You can see this usage quite clearly in the examples, but try to remove one of the cases, then you will see what I mean, hint: you will get a compile-time error, isn't that nice.
Unless enum is used and all constant cases covered, finish the switch expression with a default
This rule is a complement to the previous one, and again, you will get compiler nagging you if not done.
Some final thoughts: even though it is good to have another tool in the bag in Java, switch expression is by no means the full-fledged pattern matching as some might expect, it only supports constant types and enums, but not class types. What that means developers would still have to stick with good old instanceof for now.
Comments
Post a Comment