
https://horstmann.com/presentations/2025/jcrete
Slide navigation: Forward with space bar, →, or swipe left. Backwards with ← or swipe right. Switch slides with PgDn and PgUp.
switch statement invented in C
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ndigit[c-'0']++;
break;
case ' ':
case '\n':
case '\t':
nwhite++;
break;
default:
nother++;
break;
}
if/else if/else if with ≥ 10 casespublic int length(LispyList lst) {
return switch (lst) {
case EmptyList _ -> 0;
case NonEmptyList(_, tail) -> 1 + length(tail);
}
}
switch and instanceofswitch on int, short, byte, charString, enum, Integer, Short, Byte, Characterswitch expressionsinstanceof patterns_ patternsfloat, double, long, boolean and their wrappersswitch: Statement/expression, fallthrough/no fallthroughcase YELLOW, GREENcase Manager m, e instanceof Manager mcase Point(double x, double y), p instanceof Point(double x, double y)case nullcase Point(double x, double y) when y > 0case Point(double x, _)case Employee e can’t be above case Manager menum Color { RED, YELLOW, GREEN };
boolean go(Color c) {
switch (c) {
case RED: return false;
case YELLOW, GREEN: return true;
}
}
enum constant—§
14.22Boolean go(Color c) {
switch (c) {
case RED: return false;
case YELLOW, GREEN: return true;
case Color _: return null;
}
}
boolean go(Color c) {
return switch (c) {
case RED -> false;
case YELLOW, GREEN -> true;
};
}
switch statements.Boolean go(Color c) {
switch (c) {
case RED: return false;
case YELLOW, GREEN: return true;
case null: return null;
}
}
case null makes it “enhanced”switch expressions throw a NullPointerException?
record Box<T>(T contents) { }
Box<String> boxed = null;
String unboxed = switch (boxed) { // ❶
case Box(String s) -> s;
};
boxed = new Box<>(null);
String unboxed = switch (boxed) { // ❷
case Box(String s) -> s;
};
Box<Box<String>> doubleBoxed = new Box<>(null);
String unboxed = switch (doubleBoxed) { // ❸
case Box(Box(String s)) -> s;
};
nullMatchError!sealed interface Shape {}
record Rect(double x, double y) implements Shape {}
record Square(double x) implements Shape {}
public List<Shape> dareToBeSquare(List<Shape> shapes) {
return shapes.stream()
.map(s -> switch(s) {
case Rect(int x, _) -> new Square(x);
default -> s;
})
.toList();
}
public List<Shape> dareToBeSquare(List<Shape> shapes) {
return shapes.stream()
.map(s -> switch(s) {
case Rect(int x, _) -> new Square(x);
case Square _ -> s;
})
.toList();
}
switch expressions?
Object x = ...;
String result = switch (x) { // ❶
case "" -> "empty";
case 0 -> "zero";
default -> "something else";
};
enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
Object y = ...;
result = switch (y) { // ❷
case Size.EXTRA_LARGE -> "extra large";
default -> "something else";
};
Objectcase "", case 0) can’t be used with ObjectSize.EXTRA_LARGE is a constant caseenum to deal with
sealed interface JSONValue {}
record JSONNumber(double x) implements JSONValue {}
enum JSONBoolean { FALSE, TRUE } implements JSONValue {}
Size.EXTRA_LARGE?void main() {
int count = 0;
float sum = 0;
for (int i = 1; i <= 100; i++) {
if (1.0 / i instanceof float f) {
count++;
sum += f;
}
}
IO.println(count + " " + sum);
}
100 5.1873781.0 / i is an “instance” of floatpublic class Point { // Not a record
private double x, y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public inverse Point(double x, double y) {
x = this.x;
y = this.y;
}
}
Suppose the j.u.r.Pattern class is enhanced with this deconstructor:
public inverse String match(String... groups) {
Matcher m = matcher(that); // *that* is the match candidate
if (m.matches()) // receiver for matcher() is the Pattern
__yield IntStream.range(1, m.groupCount())
.map(m::group)
.toArray(String[]::new);
}
What is the result of
switch("0:59") {
case Pattern.of("([0-2][0-9]):([0-9]+)").match(h, m) ->
60 * Integer.parseInt(h) + Integer.parseInt(m);
default -> -1;
}
MatchError is throwngroups is not used
switch and instanceof for pattern matching leverages existing knowledgenulldefault