Pattern Matching in Switch - Java
Switch has come a long way from being a limited control structure to now supporting expressive features like switch expressions (finalized in Java 14) and pattern matching (finalized in Java 21). Pain points See how verbose and complex the code below looks. We are null proofing checking the type using instanceof manually casting This means that if you need to introduce more types in the future, you will end up with more if-else branches, manual checks and boilerplate code. static void verboseDisplay(Object obj) { String result = ""; if(Objects.nonNull(obj)) { if (obj instanceof String) { String str = (String) obj; int len = str.length(); result = String.format("We have got string %s of length %d", str, len); } else if (obj instanceof Integer) { Integer num = (Integer) obj; result = String.format("We have got integer %d", num); } else { result = String.format("We have got %s of type %s", obj, obj.getClass().getName()); } } System.out.println(result); } Doesn't this look better? I have refactored the above code using switch expression and pattern matching. static void cleanDisplay(Object obj) { String result = switch(obj) { case null -> ""; case String str -> String.format("We have got a string %s of length %d", str, str.length()); case Integer num -> String.format("We have got an integer %d", num); default -> String.format("We have got %s of type %s", obj, obj.getClass().getName()); }; System.out.println(result); } We have moved away from if-else branching explicit null checks type checks using instanceof manual type casting repetitive assignments inside case blocks Let's break it down We have used switch expression with arrow(->) and default case, instead of traditional switch with colon (:) and break statements. Since Java 21, null can be added as a valid case label.

Switch has come a long way from being a limited control structure to now supporting expressive features like switch expressions (finalized in Java 14) and pattern matching (finalized in Java 21).
Pain points
See how verbose and complex the code below looks. We are
- null proofing
- checking the type using instanceof
- manually casting
This means that if you need to introduce more types in the future, you will end up with more if-else branches, manual checks and boilerplate code.
static void verboseDisplay(Object obj) {
String result = "";
if(Objects.nonNull(obj)) {
if (obj instanceof String) {
String str = (String) obj;
int len = str.length();
result = String.format("We have got string %s of length %d", str, len);
} else if (obj instanceof Integer) {
Integer num = (Integer) obj;
result = String.format("We have got integer %d", num);
} else {
result = String.format("We have got %s of type %s", obj, obj.getClass().getName());
}
}
System.out.println(result);
}
Doesn't this look better?
I have refactored the above code using switch expression and pattern matching.
static void cleanDisplay(Object obj) {
String result = switch(obj) {
case null -> "";
case String str -> String.format("We have got a string %s of length %d", str, str.length());
case Integer num -> String.format("We have got an integer %d", num);
default -> String.format("We have got %s of type %s", obj, obj.getClass().getName());
};
System.out.println(result);
}
We have moved away from
- if-else branching
- explicit null checks
- type checks using instanceof
- manual type casting
- repetitive assignments inside case blocks
Let's break it down
- We have used switch expression with arrow(->) and default case, instead of traditional switch with colon (:) and break statements. Since Java 21, null can be added as a valid case label.