Add patterns module: pattern matching from JDK 21 to 27
Type, record and primitive patterns, guards, sealed exhaustiveness, MatchException via separate compilation, and eight captured transcripts. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01TF9JWFvJSNm6HVzswzZU5a
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
$ javac src/TypePatterns.java && java TypePatterns (21.0.10+7-Ubuntu-124.04)
|
||||
string of length 5 / string of length 5
|
||||
3 -1
|
||||
int 42
|
||||
string JAVA
|
||||
int array of 3
|
||||
other Double
|
||||
|
||||
$ javac src/TypePatterns.java && java TypePatterns (25.0.4.1+1-LTS)
|
||||
string of length 5 / string of length 5
|
||||
3 -1
|
||||
int 42
|
||||
string JAVA
|
||||
int array of 3
|
||||
other Double
|
||||
|
||||
$ javac src/TypePatterns.java && java TypePatterns (27+35)
|
||||
string of length 5 / string of length 5
|
||||
3 -1
|
||||
int 42
|
||||
string JAVA
|
||||
int array of 3
|
||||
other Double
|
||||
@@ -0,0 +1,39 @@
|
||||
$ javac src/Guards.java && java Guards (25.0.4.1+1-LTS)
|
||||
empty string
|
||||
short string: abc
|
||||
long string: abcdefgh
|
||||
negative -4
|
||||
int 12
|
||||
other
|
||||
|
||||
$ javac src/Guards.java && java Guards (27+35)
|
||||
empty string
|
||||
short string: abc
|
||||
long string: abcdefgh
|
||||
negative -4
|
||||
int 12
|
||||
other
|
||||
|
||||
$ javac broken/Dominated.java (25.0.4.1+1-LTS)
|
||||
broken/Dominated.java:5: error: this case label is dominated by a preceding case label
|
||||
case String s -> "string"; // String is a CharSequence, so this can never be reached
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/Dominated.java (27+35)
|
||||
broken/Dominated.java:5: error: this case label is dominated by a preceding case label
|
||||
case String s -> "string"; // String is a CharSequence, so this can never be reached
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/GuardBeforeGeneral.java (25.0.4.1+1-LTS)
|
||||
broken/GuardBeforeGeneral.java:5: error: this case label is dominated by a preceding case label
|
||||
case String s when s.isEmpty() -> "empty string"; // guarded case after the unguarded one
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/GuardBeforeGeneral.java (27+35)
|
||||
broken/GuardBeforeGeneral.java:5: error: this case label is dominated by a preceding case label
|
||||
case String s when s.isEmpty() -> "empty string"; // guarded case after the unguarded one
|
||||
^
|
||||
1 error
|
||||
@@ -0,0 +1,31 @@
|
||||
$ javac src/RecordPatterns.java && java RecordPatterns (21.0.10+7-Ubuntu-124.04)
|
||||
point at 3,4
|
||||
not a point
|
||||
7
|
||||
box of string hi
|
||||
box of int 7
|
||||
box of 2.5
|
||||
|
||||
$ javac src/RecordPatterns.java && java RecordPatterns (25.0.4.1+1-LTS)
|
||||
point at 3,4
|
||||
not a point
|
||||
7
|
||||
box of string hi
|
||||
box of int 7
|
||||
box of 2.5
|
||||
|
||||
$ javac src/RecordPatterns.java && java RecordPatterns (27+35)
|
||||
point at 3,4
|
||||
not a point
|
||||
7
|
||||
box of string hi
|
||||
box of int 7
|
||||
box of 2.5
|
||||
|
||||
$ javac src/MatchExceptionDemo.java && java MatchExceptionDemo (25.0.4.1+1-LTS)
|
||||
MatchException: java.lang.IllegalStateException: accessor blew up
|
||||
cause: java.lang.IllegalStateException: accessor blew up
|
||||
|
||||
$ javac src/MatchExceptionDemo.java && java MatchExceptionDemo (27+35)
|
||||
MatchException: java.lang.IllegalStateException: accessor blew up
|
||||
cause: java.lang.IllegalStateException: accessor blew up
|
||||
@@ -0,0 +1,54 @@
|
||||
$ javac src/SealedExhaustive.java && java SealedExhaustive (21.0.10+7-Ubuntu-124.04)
|
||||
Circle[r=1.0] -> 3.14
|
||||
Square[side=2.0] -> 4.00
|
||||
Rect[w=2.0, h=3.0] -> 6.00
|
||||
|
||||
$ javac src/SealedExhaustive.java && java SealedExhaustive (25.0.4.1+1-LTS)
|
||||
Circle[r=1.0] -> 3.14
|
||||
Square[side=2.0] -> 4.00
|
||||
Rect[w=2.0, h=3.0] -> 6.00
|
||||
|
||||
$ javac src/SealedExhaustive.java && java SealedExhaustive (27+35)
|
||||
Circle[r=1.0] -> 3.14
|
||||
Square[side=2.0] -> 4.00
|
||||
Rect[w=2.0, h=3.0] -> 6.00
|
||||
|
||||
$ javac broken/NotExhaustive.java (21.0.10+7-Ubuntu-124.04)
|
||||
broken/NotExhaustive.java:8: error: the switch expression does not cover all possible input values
|
||||
return switch (s) {
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/NotExhaustive.java (25.0.4.1+1-LTS)
|
||||
broken/NotExhaustive.java:8: error: the switch expression does not cover all possible input values
|
||||
return switch (s) {
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/NotExhaustive.java (27+35)
|
||||
broken/NotExhaustive.java:8: error: the switch expression does not cover all possible input values
|
||||
return switch (s) {
|
||||
^
|
||||
missing patterns:
|
||||
Rect _
|
||||
1 error
|
||||
|
||||
$ javac broken/NotExhaustiveObject.java (21.0.10+7-Ubuntu-124.04)
|
||||
broken/NotExhaustiveObject.java:3: error: the switch expression does not cover all possible input values
|
||||
return switch (o) {
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/NotExhaustiveObject.java (25.0.4.1+1-LTS)
|
||||
broken/NotExhaustiveObject.java:3: error: the switch expression does not cover all possible input values
|
||||
return switch (o) {
|
||||
^
|
||||
1 error
|
||||
|
||||
$ javac broken/NotExhaustiveObject.java (27+35)
|
||||
broken/NotExhaustiveObject.java:3: error: the switch expression does not cover all possible input values
|
||||
return switch (o) {
|
||||
^
|
||||
missing patterns:
|
||||
Object _
|
||||
1 error
|
||||
@@ -0,0 +1,32 @@
|
||||
$ java -cp old Client (Client and Shape compiled together, v1) (25.0.4.1+1-LTS)
|
||||
circle: 3.141592653589793
|
||||
square: 4.0
|
||||
|
||||
$ java -cp new:old Main (Shape gained Triangle; Client.class NOT recompiled) (25.0.4.1+1-LTS)
|
||||
Exception in thread "main" java.lang.MatchException
|
||||
at Client.area(Client.java:4)
|
||||
at Main.main(Main.java:4)
|
||||
|
||||
$ javac -cp new sep/client/Client.java (now recompile Client against v2) (25.0.4.1+1-LTS)
|
||||
sep/client/Client.java:4: error: the switch expression does not cover all possible input values
|
||||
return switch (s) {
|
||||
^
|
||||
1 error
|
||||
|
||||
$ java -cp old Client (Client and Shape compiled together, v1) (27+35)
|
||||
circle: 3.141592653589793
|
||||
square: 4.0
|
||||
|
||||
$ java -cp new:old Main (Shape gained Triangle; Client.class NOT recompiled) (27+35)
|
||||
Exception in thread "main" java.lang.MatchException
|
||||
at Client.area(Client.java:4)
|
||||
at Main.main(Main.java:4)
|
||||
|
||||
$ javac -cp new sep/client/Client.java (now recompile Client against v2) (27+35)
|
||||
sep/client/Client.java:4: error: the switch expression does not cover all possible input values
|
||||
return switch (s) {
|
||||
^
|
||||
missing patterns:
|
||||
Triangle _
|
||||
1 error
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
$ javac src/NullCase.java && java NullCase (25.0.4.1+1-LTS)
|
||||
without case null: NullPointerException
|
||||
with case null: null!
|
||||
case null, default: null or something else
|
||||
instanceof with null: false
|
||||
|
||||
$ javac src/NullCase.java && java NullCase (27+35)
|
||||
without case null: NullPointerException
|
||||
with case null: null!
|
||||
case null, default: null or something else
|
||||
instanceof with null: false
|
||||
|
||||
$ javac src/Unnamed.java && java Unnamed (21.0.10+7-Ubuntu-124.04)
|
||||
src/Unnamed.java:9: error: unnamed variables are a preview feature and are disabled by default.
|
||||
case Circle _ -> "round"; // the type matters, the value does not
|
||||
^
|
||||
(use --enable-preview to enable unnamed variables)
|
||||
1 error
|
||||
|
||||
$ javac src/Unnamed.java && java Unnamed (25.0.4.1+1-LTS)
|
||||
round angular
|
||||
5
|
||||
|
||||
$ javac src/Unnamed.java && java Unnamed (27+35)
|
||||
round angular
|
||||
5
|
||||
@@ -0,0 +1,87 @@
|
||||
$ javac preview/PrimitiveInstanceof.java (25.0.4.1+1-LTS)
|
||||
preview/PrimitiveInstanceof.java:3: error: primitive patterns are a preview feature and are disabled by default.
|
||||
if (i instanceof byte b) return i + " fits in a byte: " + b;
|
||||
^
|
||||
(use --enable-preview to enable primitive patterns)
|
||||
1 error
|
||||
|
||||
$ javac preview/PrimitiveInstanceof.java (27+35)
|
||||
preview/PrimitiveInstanceof.java:3: error: primitive patterns are a preview feature and are disabled by default.
|
||||
if (i instanceof byte b) return i + " fits in a byte: " + b;
|
||||
^
|
||||
(use --enable-preview to enable primitive patterns)
|
||||
1 error
|
||||
|
||||
$ javac --enable-preview --release 25 preview/PrimitiveInstanceof.java && java --enable-preview PrimitiveInstanceof (25.0.4.1+1-LTS)
|
||||
100 fits in a byte: 100
|
||||
1000 fits in a short: 1000
|
||||
100000 needs an int
|
||||
0.5 converts to float 0.5 without loss
|
||||
0.1 does NOT convert to float without loss
|
||||
|
||||
$ javac --enable-preview --release 27 preview/PrimitiveInstanceof.java && java --enable-preview PrimitiveInstanceof (27+35)
|
||||
100 fits in a byte: 100
|
||||
1000 fits in a short: 1000
|
||||
100000 needs an int
|
||||
0.5 converts to float 0.5 without loss
|
||||
0.1 does NOT convert to float without loss
|
||||
|
||||
$ javac --enable-preview --release 25 preview/PrimitiveSwitch.java && java --enable-preview PrimitiveSwitch (25.0.4.1+1-LTS)
|
||||
OK | other success 204 | client error 404 | something else 500
|
||||
yes no
|
||||
zero one many (9223372036854775807)
|
||||
|
||||
$ javac --enable-preview --release 27 preview/PrimitiveSwitch.java && java --enable-preview PrimitiveSwitch (27+35)
|
||||
OK | other success 204 | client error 404 | something else 500
|
||||
yes no
|
||||
zero one many (9223372036854775807)
|
||||
|
||||
$ javac --enable-preview --release 25 preview/PrimitiveInRecord.java && java --enable-preview PrimitiveInRecord (25.0.4.1+1-LTS)
|
||||
whole degrees: 21
|
||||
fractional: 21.5
|
||||
not a reading
|
||||
|
||||
$ javac --enable-preview --release 27 preview/PrimitiveInRecord.java && java --enable-preview PrimitiveInRecord (27+35)
|
||||
whole degrees: 21
|
||||
fractional: 21.5
|
||||
not a reading
|
||||
|
||||
$ javac --enable-preview --release 25 preview/PrimitiveEdges.java && java --enable-preview PrimitiveEdges (25.0.4.1+1-LTS)
|
||||
0.0 int? true float? true
|
||||
-0.0 int? false float? true
|
||||
NaN int? false float? true
|
||||
1.6777217E7 int? true float? false
|
||||
1.0E10 int? false float? true
|
||||
3.0 int? true float? true
|
||||
1099511627776 instanceof int? false
|
||||
Object holding Integer matches int pattern: 42
|
||||
Short in Object does not match int
|
||||
65 as char: A
|
||||
|
||||
$ javac --enable-preview --release 27 preview/PrimitiveEdges.java && java --enable-preview PrimitiveEdges (27+35)
|
||||
0.0 int? true float? true
|
||||
-0.0 int? false float? true
|
||||
NaN int? false float? true
|
||||
1.6777217E7 int? true float? false
|
||||
1.0E10 int? false float? true
|
||||
3.0 int? true float? true
|
||||
1099511627776 instanceof int? false
|
||||
Object holding Integer matches int pattern: 42
|
||||
Short in Object does not match int
|
||||
65 as char: A
|
||||
|
||||
$ javac --enable-preview --release 25 preview/BoxedToNarrower.java && java --enable-preview BoxedToNarrower (25.0.4.1+1-LTS)
|
||||
preview/BoxedToNarrower.java:4: error: incompatible types: Integer cannot be converted to byte
|
||||
if (boxed instanceof byte b) System.out.println("fits a byte: " + b); // Integer to byte is not allowed
|
||||
^
|
||||
1 error
|
||||
Error: Could not find or load main class BoxedToNarrower
|
||||
Caused by: java.lang.ClassNotFoundException: BoxedToNarrower
|
||||
|
||||
$ javac --enable-preview --release 27 preview/BoxedToNarrower.java && java --enable-preview BoxedToNarrower (27+35)
|
||||
preview/BoxedToNarrower.java:4: error: incompatible types: Integer cannot be converted to byte
|
||||
if (boxed instanceof byte b) System.out.println("fits a byte: " + b); // Integer to byte is not allowed
|
||||
^
|
||||
1 error
|
||||
Error: Could not find or load main class BoxedToNarrower
|
||||
Caused by: java.lang.ClassNotFoundException: BoxedToNarrower
|
||||
@@ -0,0 +1,11 @@
|
||||
$ javap -v PrimitiveSwitch | grep -E 'minor|major' (compiled by 25.0.4.1+1-LTS with --enable-preview)
|
||||
minor version: 65535
|
||||
major version: 69
|
||||
|
||||
$ java --enable-preview PrimitiveSwitch (class compiled on 25, run on 27+35)
|
||||
Error: LinkageError occurred while loading main class PrimitiveSwitch
|
||||
java.lang.UnsupportedClassVersionError: PrimitiveSwitch (class file version 69.65535) was compiled with preview features that are unsupported. This version of the Java Runtime only recognizes preview features for class file version 71.65535
|
||||
|
||||
$ java PrimitiveSwitch (same class, no flag, run on 25.0.4.1+1-LTS)
|
||||
Error: LinkageError occurred while loading main class PrimitiveSwitch
|
||||
java.lang.UnsupportedClassVersionError: Preview features are not enabled for PrimitiveSwitch (class file version 69.65535). Try running with '--enable-preview'
|
||||
Reference in New Issue
Block a user