/* * @test /nodynamiccopyright/ * @bug 8206986 8222169 8224031 8240964 8267119 8268670 8321582 * @summary Check expression switch works. * @compile ExpressionSwitch.java * @run main ExpressionSwitch */ // * @compile/fail/ref=ExpressionSwitch-old.out --release 9 -XDrawDiagnostics ExpressionSwitch.java import java.util.Objects; import java.util.function.Supplier; public class ExpressionSwitch { public static void main(String... args) { new ExpressionSwitch().run(); } private void run() { check(T.A, "A"); check(T.B, "B"); check(T.C, "other"); assertEquals(exhaustive1(T.C), "C"); assertEquals(scopesIsolated(T.B), "B"); assertEquals(lambdas1(T.B).get(), "B"); assertEquals(lambdas2(T.B).get(), "B"); assertEquals(convert1("A"), 0); assertEquals(convert1("B"), 0); assertEquals(convert1("C"), 1); assertEquals(convert1(""), -1); assertEquals(convert1(null), -2); assertEquals(convert2("A"), 0); assertEquals(convert2("B"), 0); assertEquals(convert2("C"), 1); assertEquals(convert2(""), -1); localClass(T.A); assertEquals(castSwitchExpressions(T.A), "A"); testTypeInference(true, 0); assertEquals(yieldPrimitiveDotClass("byte"), byte.class); assertEquals(yieldPrimitiveDotClass("char"), char.class); assertEquals(yieldPrimitiveDotClass("short"), short.class); assertEquals(yieldPrimitiveDotClass("int"), int.class); assertEquals(yieldPrimitiveDotClass("long"), long.class); assertEquals(yieldPrimitiveDotClass("float"), float.class); assertEquals(yieldPrimitiveDotClass("double"), double.class); assertEquals(yieldPrimitiveDotClass("void"), void.class); assertEquals(yieldPrimitiveDotClass("boolean"), boolean.class); assertEquals(yieldPrimitiveDotClass("other"), null); } private String print(T t) { return switch (t) { case A -> "A"; case B -> { yield "B"; } default -> { yield "other"; } }; } private String exhaustive1(T t) { return switch (t) { case A -> "A"; case B -> { yield "B"; } case C -> "C"; case D -> "D"; }; } private String exhaustive2(T t) { return switch (t) { case A -> "A"; case B -> "B"; case C -> "C"; case D -> "D"; }; } private String scopesIsolated(T t) { return switch (t) { case A -> { String res = "A"; yield res;} case B -> { String res = "B"; yield res;} default -> { String res = "default"; yield res;} }; } private Supplier lambdas1(T t) { return switch (t) { case A -> () -> "A"; case B -> { yield () -> "B"; } default -> () -> "default"; }; } private Supplier lambdas2(T t) { return switch (t) { case A: yield () -> "A"; case B: { yield () -> "B"; } default: yield () -> "default"; }; } private int convert1(String s) { return s == null ? -2 : switch (s) { case "A", "B" -> 0; case "C" -> { yield 1; } default -> -1; }; } private int convert2(String s) { return switch (s) { case "A", "B": yield 0; case "C": yield 1; default: yield -1; }; } private Object yieldDisambiguationLiterals(String s) { return switch (s) { case "a": yield 0; case "b": yield 0L; case "c": yield 0.0f; case "d": yield 0.0d; case "e": yield true; case "f": yield false; case "g": yield '0'; case "h": yield ""; case "i": yield null; default: yield 0; }; } private int yieldUnaryNumberOperator(String s, int a) { return switch (s) { case "a": yield +a; case "b": yield -a; case "c": yield ~a; // intentionally repeated ~a, test the case clause case "d": yield ++a; case "e": yield --a; case "f": yield a++; case "g": yield a--; default: yield ~a; // intentionally repeated ~a, test the default clause }; } private boolean yieldUnaryNotOperator(String s, boolean b) { return switch (s) { case "a": yield !b; // intentionally repeated !b, test the case clause default: yield !b; // intentionally repeated !b, test the default clause }; } private Class yieldPrimitiveDotClass(String s) { return switch (s) { case "byte": yield byte.class; case "char": yield char.class; case "short": yield short.class; case "int": yield int.class; case "long": yield long.class; case "float": yield float.class; case "double": yield double.class; case "void": yield void.class; case "boolean": yield boolean.class; default: yield null; }; } private void localClass(T t) { String good = "good"; class L { public String c() { STOP: switch (t) { default: break STOP; } return switch (t) { default: yield good; }; } } String result = new L().c(); if (!Objects.equals(result, good)) { throw new AssertionError("Unexpected result: " + result); } } private String castSwitchExpressions(T t) { return (String) switch (t) { case A -> "A"; default -> 1; }; } private void testTypeInference(boolean b, int i) { m(s -> s.length(), String.class); m(b ? s -> s.length() : s -> s.length(), String.class); m(switch (i) { case 0 -> s -> s.length(); default -> s -> s.length(); }, String.class); } void m(Consumer c, Class cl) {} private void check(T t, String expected) { String result = print(t); assertEquals(result, expected); } private void assertEquals(Object result, Object expected) { if (!Objects.equals(result, expected)) { throw new AssertionError("Unexpected result: " + result); } } enum T { A, B, C, D; } void t() { Runnable r = () -> {}; r.run(); } interface Consumer { public void consume(Z z); } }