You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SwitchPatternPreview3OK.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import java.util.List;
  2. import java.util.Locale;
  3. /**
  4. * Inspired by examples in https://openjdk.org/jeps/427
  5. */
  6. public class SwitchPatternPreview3OK {
  7. public static void main(String[] args) {
  8. System.out.println(formatterPatternSwitch(null));
  9. System.out.println(formatterPatternSwitch(123));
  10. System.out.println(formatterPatternSwitch(999L));
  11. System.out.println(formatterPatternSwitch(12.34));
  12. System.out.println(formatterPatternSwitch("foo"));
  13. System.out.println(formatterPatternSwitch(List.of(123, "foo", 999L, 12.34)));
  14. System.out.println(testCircle(new Rectangle()));
  15. System.out.println(testCircle(new Circle(5)));
  16. System.out.println(testCircle(new Circle(6)));
  17. System.out.println(testSealedCoverage(new A()));
  18. System.out.println(testSealedCoverage(new B()));
  19. System.out.println(testSealedCoverage(new C(5)));
  20. // constantLabelMustAppearBeforePattern(-1);
  21. // constantLabelMustAppearBeforePattern(0);
  22. // constantLabelMustAppearBeforePattern(42);
  23. // constantLabelMustAppearBeforePattern(-99);
  24. // constantLabelMustAppearBeforePattern(Integer.valueOf(123));
  25. // constantLabelMustAppearBeforePattern(null);
  26. constantLabelMustAppearBeforePatternInteger(-1);
  27. constantLabelMustAppearBeforePatternInteger(0);
  28. constantLabelMustAppearBeforePatternInteger(42);
  29. constantLabelMustAppearBeforePatternInteger(-99);
  30. constantLabelMustAppearBeforePatternInteger(Integer.valueOf(123));
  31. constantLabelMustAppearBeforePatternInteger(null);
  32. // System.out.println(testGenericSealedExhaustive(new B<Integer>()));
  33. }
  34. static String formatterPatternSwitch(Object o) {
  35. return switch (o) {
  36. case null -> "null";
  37. case Integer i -> String.format("int %d", i);
  38. case Long l -> String.format("long %d", l);
  39. case Double d -> String.format(Locale.ENGLISH, "double %f", d);
  40. case String s -> String.format("String %s", s);
  41. default -> o.toString();
  42. };
  43. }
  44. static class Shape {}
  45. static class Rectangle extends Shape {}
  46. static class Circle extends Shape {
  47. private final double radius;
  48. public Circle(double radius) { this.radius = radius; }
  49. double calculateArea() { return Math.PI * radius * radius; }
  50. }
  51. static String testCircle(Shape s) {
  52. return switch (s) {
  53. case Circle c when (c.calculateArea() > 100) -> "Large circle";
  54. case Circle c -> "Small circle";
  55. default -> "Non-circle";
  56. };
  57. }
  58. sealed interface S permits A, B, C {}
  59. final static class A implements S {}
  60. final static class B implements S {}
  61. static record C(int i) implements S {} // Implicitly final
  62. static String testSealedCoverage(S s) {
  63. return switch (s) {
  64. case A a -> "Sealed sub-class A";
  65. case B b -> "Sealed sub-class B";
  66. case C c -> "Sealed sub-record C";
  67. };
  68. }
  69. /**
  70. * According to an example from JEP 420, this should work, but it does not, neither with Javac nor ECJ.
  71. *
  72. * See:
  73. * https://openjdk.java.net/jeps/420#1b--Dominance-of-pattern-labels
  74. * https://bugs.openjdk.java.net/browse/JDK-8273326
  75. * https://bugs.eclipse.org/bugs/show_bug.cgi?id=579355
  76. *
  77. * TODO: reactivate when implemented or move to preview 3 with Java 19, Eclipse 4.24.
  78. */
  79. /*
  80. static String constantLabelMustAppearBeforePattern(Object o) {
  81. switch (o) {
  82. case null -> System.out.println("value unavailable: " + i);
  83. case -1, 1 -> System.out.println("special case:" + o);
  84. case Integer i && i > 0 -> System.out.println("positive integer: " + o);
  85. case Integer i -> System.out.println("other integer: " + o);
  86. default -> System.out.println("non-integer: " + o);
  87. }
  88. return i == null ? "null" : i.toString();
  89. }
  90. */
  91. static String constantLabelMustAppearBeforePatternInteger(Integer i) {
  92. switch (i) {
  93. case null -> System.out.println("value unavailable: " + i);
  94. case -1, 1 -> System.out.println("absolute value 1: " + i);
  95. case Integer value when value > 0 -> System.out.println("positive integer: " + i);
  96. default -> System.out.println("other integer: " + i);
  97. }
  98. return i == null ? "null" : i.toString();
  99. }
  100. static void nullCanAppearAfterConstantLabel(Integer i) {
  101. switch (i) {
  102. case -1, 1 -> System.out.println("absolute value 1: " + i);
  103. case null -> System.out.println("value unavailable: " + i);
  104. case Integer value when value > 0 -> System.out.println("positive integer: " + i);
  105. default -> System.out.println("other integer: " + i);
  106. }
  107. }
  108. static void defaultCanAppearBeforePattern(Integer i) {
  109. switch (i) {
  110. case null -> System.out.println("value unavailable: " + i);
  111. case -1, 1 -> System.out.println("absolute value 1: " + i);
  112. default -> System.out.println("other integer: " + i);
  113. case Integer value when value > 0 -> System.out.println("positive integer: " + i);
  114. }
  115. }
  116. static void defaultCanAppearBeforeNull(Integer i) {
  117. switch (i) {
  118. case -1, 1 -> System.out.println("absolute value 1: " + i);
  119. default -> System.out.println("other integer: " + i);
  120. case null -> System.out.println("value unavailable: " + i);
  121. case Integer value when value > 0 -> System.out.println("positive integer: " + i);
  122. }
  123. }
  124. static void defaultCanAppearBeforeConstantLabel(Integer i) {
  125. switch (i) {
  126. case null -> System.out.println("value unavailable: " + i);
  127. default -> System.out.println("other integer: " + i);
  128. case -1, 1 -> System.out.println("absolute value 1: " + i);
  129. case Integer value when value > 0 -> System.out.println("positive integer: " + i);
  130. }
  131. }
  132. /**
  133. * According to an example from JEP 420, this should work with preview 2 (Java 18), and it does with Javac,
  134. * but not with ECJ for Java 18 and 19.
  135. *
  136. * See:
  137. * https://openjdk.java.net/jeps/420#2--Exhaustiveness-of-switch-expressions-and-statements
  138. * https://bugs.eclipse.org/bugs/show_bug.cgi?id=579360
  139. * https://github.com/eclipse-jdt/eclipse.jdt.core/issues/587
  140. *
  141. * TODO: reactivate when implemented or move to preview 4 with Java 20.
  142. */
  143. /*
  144. sealed interface I<T> permits A, B {}
  145. final static class A<X> implements I<String> {}
  146. final static class B<Y> implements I<Y> {}
  147. static int testGenericSealedExhaustive(I<Integer> i) {
  148. return switch (i) {
  149. // Exhaustive as no A case possible!
  150. case B<Integer> bi -> 42;
  151. };
  152. }
  153. */
  154. }