import java.util.*; class Main { static class X { int f() { return 0; } } int switchTestResolve(Object o) { int i1 = switch(o) { case X x -> x.f(); default -> 1; }; int i2 = switch(o) { case null, X x -> x.f(); default -> 1; }; int i3 = switch(o) { case X x, null -> x.f(); default -> 1; }; int i4 = switch(o) { case String s, X x -> x.f(); default -> 1; }; int i5 = switch(o) { case String s, X x -> x.f(); default -> 1; }; int i6 = switch(o) { case X x, String s -> x.f(); default -> 1; }; return i1 + i2 + i3 + i4 + i5 + i6; } void checkSwitchSelectorType(boolean b, double d, int[] array) { switch (b) { case true: System.out.println("true"); break; case false: System.out.println("false"); break; } String str; str = switch(d) { case 1 -> "ok"; case 2 -> "not ok"; }; switch (array) { case int[] arr: System.out.println("true"); break; } str = switch (array) { case int[] arr -> "true"; }; // intersection type var values = List.of("foo", 3, 4.0); for (var value : values) { switch (value) { case Integer i -> System.out.println("integer !"); case String s -> System.out.println("string !"); case Object o -> System.out.println("object !"); } } } void constLabelAndSelectorCompatibility(Number n, CharSequence c, Integer i, String s) { switch (n) { case 1: System.out.println("ok"); } String str; str = switch (n) { case 1 -> "ok"; default -> "not ok"; }; switch (c) { case "ok": System.out.println("ok"); } str = switch (c) { case "ok" -> "ok"; default -> "not ok"; }; switch (i) { case '1': System.out.println("ok"); } str = switch (i) { case '1' ->"ok"; default -> "not ok"; }; switch (i) { case 1: System.out.println("ok"); } str= switch (i) { case 1 -> "ok"; default -> "not ok"; }; switch (s) { case "null" : System.out.println("null"); break; default: System.out.println("s"); } str = switch (s) { case "null" -> "null"; default -> "s"; }; } void incompatibleNullLabelAndSelector(int i) { switch (i) { case null: System.out.println("ok"); } String str; str = switch (i) { case null -> "ok"; default -> "not ok"; }; } void defaultAlwaysCompatible(int i) { switch (i) { case 1, default: System.out.println("ok"); } String str; str = switch (i) { case 1, default -> "ok"; }; } void patternsCompatibilty(I i, Object o, List list1, List list2) { switch (i) { case Sub1 s2: System.out.println("s1"); break; case Sub5 s5: System.out.println("s5"); default: System.out.println("s"); } String str; str = switch (i) { case Sub1 s2 -> "s1"; case Sub5 s5 -> "s5"; default -> "s"; }; switch (i) { // total pattern case Object oo: System.out.println("s1"); } str = switch (i) { // total pattern case Object oo -> "s1"; }; // unsafe casts switch (list1) { case List l: break; } switch (list2) { case List l: break; } switch (o) { case List ll: break; case default: break; } switch (list1) { case Object oo: break; } // null selector switch (null) { case null: break; default: break; }; str = switch (null) { case null -> "null"; default -> "def"; }; switch (o) { case int ii: break; default: break; } str = switch (o) { case int ii -> ""; default -> ""; }; } private static final int constant = 1; void duplicateLabels(Integer i) { String str; switch (i) { case 1: break; case Main.constant: break; } str = switch (i) { case 1 -> ""; case constant -> ""; }; // A switch label may not use more than one default label switch (i) { case 1, default: System.out.println("s1"); break; default: System.out.println("s"); } str = switch (i) { case 1, default -> "s1"; default -> "s"; }; switch (i) { case default: System.out.println("s1"); break; case default: System.out.println("s"); } str = switch (i) { case default -> "s1"; case default -> "s"; }; // A switch label may not have more than one default case label element switch (i) { case default, default: System.out.println("s"); } str = switch (i) { case default, default -> "s"; }; // A switch label may not have more than one null case label element. switch (i) { case 1, null: System.out.println("s"); case null: System.out.println("null"); } str = switch (i) { case 1, null -> "s"; case null -> "null"; }; } void fallThroughToPatterns(Object o, Integer ii) { // If a switch label has a null case label element then if the switch label also has any pattern case element labels, t // they must be type patterns (14.30.1). switch (o) { case Integer i && i != null, null: break; case default: break; } String str; str = switch (o) { case Integer i && i != null, null -> "s"; default -> "null"; }; switch (o) { case null, Integer i && i != null: break; case default: break; } str = switch (o) { case null, Integer i && i != null -> "s"; default -> "null"; }; switch (o) { case null: case Integer i && i != null: break; case default: break; } str = switch (o) { case null: case Object i && i != null: yield "sfds"; }; str = switch (o) { case null, Object i && i != null -> "sfds"; case default -> "fsd"; }; switch (o) { case null: case Integer i: break; case default: break; } str = switch (o) { case null: case Integer i: yield "s"; case default: yield "d"; }; // A switch label may not have more than one pattern case label element. switch (o) { case Integer i, Long l && l != null: System.out.println("s"); default: System.out.println("null"); } str = switch (o) { case Integer i, Long l && l != null -> "s"; default -> "null"; }; switch (o) { case Integer i: case Long l: System.out.println("s"); default: System.out.println("null"); } str = switch (o) { case Integer i: case Long l: yield "s"; default: yield "res"; }; // A switch label may not have both a pattern case label element and a default case label element. switch (o) { case Integer i, default: System.out.println("s"); } str = switch (o) { case Integer i, default -> "s"; }; switch (o) { case default, Integer i: System.out.println("s"); } str = switch (o) { case default, Integer i -> "s"; }; switch (o) { case Integer i: case default: System.out.println("s"); } str = switch (o) { case Integer i: case default: yield "s"; }; switch (ii) { case Integer i && i > 1: default: System.out.println("null"); } str = switch (ii) { case Integer i && i > 1: default: yield "null"; }; // If a switch label has a constant case label element then if the switch label also has other case element labels // they must be either a constant case label element, the default case label element, or the null case label element. switch (ii) { case 1, Integer i1 && i1 > 5: System.out.println("s1"); break; default: System.out.println("null"); } str = switch (ii) { case 1, Integer i1 && i1 > 5 -> "s1"; default -> "null"; }; switch (ii) { case Integer i1 && i1 > 5, 1: System.out.println("s1"); break; default: System.out.println("null"); } str = switch (ii) { case Integer i1 && i1 > 5, 1 -> "s1"; default -> "null"; }; switch (ii) { case 1, 2: case null, Integer i1 && i1 > 5: System.out.println("s1"); break; default: System.out.println("null"); } // more complex case switch (ii) { case 1, null, Integer i1 && i1 > 5, default: System.out.println("s1"); break; } str = switch (ii) { case 1, null, Integer i1 && i1 > 5, default -> "s1"; }; str = switch (ii) { case 1, 2, Integer i1 && i1 > 5: case null: System.out.println("s1"); yield "s1"; default: yield "def"; }; /** * It is a compile-time error if there is a statement in a switch block that consists of switch-labeled statement groups * for which both of the following are true: * It is labeled with a switch label that has a pattern case label element whose pattern introduces a pattern variable. * There is a statement preceding it in the switch block and that statement can completely normally (14.22). */ switch (o) { case default: System.out.println("def"); case Float d: System.out.println("float"); } switch (o) { case null, Integer i: if (o != null) { throw new IllegalArgumentException(""); } case Float d: System.out.println("float"); } switch (o) { case null: if (o != null) { throw new IllegalArgumentException(""); } break; case Float d: System.out.println("float"); default: System.out.println("ok"); } // switch expressions str = switch (o) { case null, Integer i: if (o != null) { throw new IllegalArgumentException(""); } case Float d: System.out.println("float"); default: yield "1"; }; str = switch (o) { case null: if (o != null) { throw new IllegalArgumentException(""); } yield "1"; case Float d: System.out.println("float"); default: yield "1"; }; } void dominance(Object o, Integer ii, String s, Day d) { // A switch label that has a pattern case label element p dominates another switch label that has a pattern case label element q if p dominates q switch (o) { case List n: System.out.println("num"); break; case List i: System.out.println("int"); break; default: System.out.println("def"); break; } String str; str = switch (o) { case List n -> "num"; case List i -> "int"; default -> "def"; }; switch (o) { case Number n: System.out.println("num"); break; case Integer i: System.out.println("int"); break; default: System.out.println("def"); break; } str = switch (o) { case Number n -> "num"; case Integer i -> "int"; default -> "def"; }; // Dominance permits a guarded pattern to be followed by its unguarded form: switch (o) { case Integer o1 && o1 != null: System.out.println("num"); break; case Integer i: System.out.println("int"); break; default: System.out.println("def"); break; } str = switch (o) { case Integer o1 && o1 != null -> "num"; case Integer i -> "int"; default -> "def"; }; switch (o) { case (Integer i): System.out.println("int"); break; case Integer o1 && o1 != null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (o) { case (Integer i) -> "num"; case Integer o1 && o1 != null -> "int"; default -> "def"; }; switch (o) { case (Integer o1 && o1 > 5): System.out.println("int"); break; case Integer o2 && o2 != null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (o) { case (Integer o1 && o1 > 5) -> "num"; case Integer o2 && o2 != null -> "int"; default -> "def"; }; switch (o) { case (Number i && false): System.out.println("int"); break; case Integer o2 && o2 != null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (o) { case (Number i && false) -> "num"; case Integer o2 && o2 != null -> "int"; default -> "def"; }; switch (o) { case (Integer i && true): System.out.println("int"); break; case (Integer o2 && o2 != null): System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (o) { case (Integer i && true) -> "num"; case (Integer o2 && o2 != null) -> "int"; default -> "def"; }; // A switch label that has a pattern case label element p that is total for the type of the selector expression // of the enclosing switch statement or switch expression dominates a switch label that has a null case label element. switch (ii) { case Object obj: System.out.println("int"); break; case null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (ii) { case Object obj -> "num"; case null -> "int"; default -> "def"; }; switch (ii) { case Object obj, null: System.out.println("int"); break; default: System.out.println("def"); break; } str = switch (ii) { case Object obj, null -> "int"; default -> "def"; }; switch (ii) { case (Integer i && true): System.out.println("int"); break; case null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (ii) { case (Integer i && true) -> "int"; case null -> "int"; default -> "def"; }; switch (ii) { case ((Integer i && false)): System.out.println("int"); break; case null: System.out.println("num"); break; default: System.out.println("def"); break; } str = switch (ii) { case ((Integer i && false)) -> "int"; case null -> "int"; default -> "def"; }; // A switch label that has a pattern case label element p dominates another switch label that has a constant case label element c // if either of the following is true: //the type of c is a primitive type and its wrapper class is a subtype of the erasure of the type of p. //the type of c is a reference type and is a subtype of the erasure of the type of p. switch (ii) { case Integer i: break; case 1: case 2: break; } str = switch (s) { case String sss -> "s"; case "1", "2" -> "1"; }; // !!! here are some contradictory examples with spec, but javac still compiles them. To be discussed in the mailing list // at least for now it's look quite logical if we have a total pattern in a switch label, and following constant switch label, // then the first switch label dominates the second one. switch (d) { case Day dd: break; case MONDAY: break; } str = switch (ii) { case Integer in && in != null -> ""; case 1 -> ""; case default -> ""; }; switch (d) { case (Day dd && true): break; case MONDAY: break; } } void completeness(Day d, I i, I2 i2, I3 i3) { // old style switch, no completeness check switch (d) { case MONDAY, TUESDAY -> System.out.println("ok"); } // If the type of the selector expression is an enum type E String str; switch (d) { case Day dd && dd != null: System.out.println("ok"); case MONDAY: System.out.println("mon"); }; switch (d) { case Day dd && dd != null: System.out.println("ok"); }; str = switch (d) { case MONDAY, TUESDAY -> System.out.println("ok"); }; str = switch (d) { case MONDAY, TUESDAY, WEDNESDAY -> "ok"; }; str = switch (d) { case MONDAY, TUESDAY, default -> "ok"; }; switch (d) { case ((Day dd && true)): System.out.println("ok"); default: // blah blah blah System.out.println("mon"); }; switch (d) { case ((Day dd && dd != null)): System.out.println("ok"); default: System.out.println("mon"); }; // If the type of the selector expression, T, names a sealed interface or a sealed class that is abstract switch(i) { case Sub1 s1: System.out.println("ok"); break; case Sub2 s2: System.out.println("ok"); break; case Sub3 s3: System.out.println("ok"); break; } str = switch(i) { case Sub1 s1 -> "ok"; case Sub2 s2 -> "ok"; case Sub3 s3 && true -> "ok"; }; switch (i) { case Sub1 s1: System.out.println("ok"); break; case Sub2 s2: System.out.println("ok"); break; } str = switch(i) { case Sub1 s1 -> "ok"; case Sub2 s2 -> "ok"; }; switch (i) { case Sub1 s1: System.out.println("ok"); break; case Sub2 s2: System.out.println("ok"); break; case Sub4 s4: System.out.println("ok"); break; case Sub6 s6: System.out.println("ok"); break; } str = switch(i) { case Sub1 s1 -> "ok"; case Sub2 s2 -> "ok"; case Sub4 s4 -> "ok"; case Sub6 s6 -> "ok"; }; switch (i) { case Sub1 s1: break; case (Sub2 s2 && false): break; case Sub3 s3: break; } str = switch(i) { case I ii && ii != null -> "ok"; }; switch (i3) { case (Sub9 s && true): break; case Sub11 s: break; case Sub12 s && true: break; } // If the type of the selector expression, T, is not an enum type and also does not name a sealed interface or a sealed class that is abstract switch (i2) { case Sub7 s1: System.out.println("ok"); break; case Sub8 s2: System.out.println("ok"); break; } str = switch (i2) { case Sub7 s1 -> "ok"; case Sub8 s2 -> "ok"; }; // empty switches switch (d) { } str = switch (d) { }; switch (i) { } str = switch (i) { }; switch (i2) { } str = switch (i2) { }; } } sealed interface I { } enum Day { MONDAY, TUESDAY, WEDNESDAY } final class Sub1 implements I { } final class Sub2 implements I { } sealed class Sub3 implements I { } final class Sub4 extends Sub3 { } final class Sub5 { } final class Sub6 extends Sub3 { } interface I2 { } class Sub7 implements I2 { } class Sub8 implements I2 { } sealed interface I3 { } final class Sub9 implements I3 { } sealed abstract class Sub10 implements I3 { } final class Sub11 extends Sub10 { } final class Sub12 extends Sub10 { }