Java 27 and 26: runnable demos and captured output for every JEP, plus version lanes
Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B38FGKKam5SCGgwgduVAh3
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* JEP 532, Primitive Types in Patterns, instanceof, and switch (fifth preview).
|
||||
*
|
||||
* <p>Until now patterns worked on reference types only. With this preview a pattern can name a
|
||||
* primitive type, and the test is "can this value be converted to that type WITHOUT losing
|
||||
* information?" Explained in docs/05-primitive-patterns.md. Compile and run with --enable-preview.
|
||||
*/
|
||||
public class PrimitivePatterns {
|
||||
|
||||
record Reading(int celsius) {}
|
||||
|
||||
public static void main(String[] args) {
|
||||
exactness();
|
||||
switchOnLong();
|
||||
switchOnObject();
|
||||
recordPattern();
|
||||
}
|
||||
|
||||
/** instanceof with a primitive type asks: is this an EXACT conversion? */
|
||||
static void exactness() {
|
||||
System.out.println("--- instanceof <primitive>: an exact-conversion test, not a cast");
|
||||
int small = 100, big = 300;
|
||||
boolean a = small instanceof byte;
|
||||
boolean b = big instanceof byte;
|
||||
System.out.println("100 instanceof byte = " + a);
|
||||
System.out.println("300 instanceof byte = " + b + " (a byte holds -128..127)");
|
||||
Check.that(a && !b, "100 converts to byte exactly, 300 does not");
|
||||
|
||||
if (small instanceof byte narrow) {
|
||||
System.out.println("binding: byte narrow = " + narrow);
|
||||
}
|
||||
|
||||
int precise = 16_777_217; // 2^24 + 1: the first int a float cannot hold
|
||||
boolean f1 = 16_777_216 instanceof float;
|
||||
boolean f2 = precise instanceof float;
|
||||
System.out.println("16_777_216 instanceof float = " + f1);
|
||||
System.out.println("16_777_217 instanceof float = " + f2 + " (float has a 24-bit significand)");
|
||||
Check.that(f1 && !f2, "int to float is exact up to 2^24 and lossy after");
|
||||
}
|
||||
|
||||
/** switch over a long, with a primitive pattern and a guard. */
|
||||
static String classify(long value) {
|
||||
return switch (value) {
|
||||
case 0L -> "zero";
|
||||
case 1L -> "one";
|
||||
case long v when v < 0 -> "negative (" + v + ")";
|
||||
case long v -> "positive (" + v + ")";
|
||||
};
|
||||
}
|
||||
|
||||
static void switchOnLong() {
|
||||
System.out.println("--- switch on a long, with pattern labels and a guard");
|
||||
for (long v : new long[] {0, 1, -7, 9_000_000_000L}) {
|
||||
System.out.println("classify(" + v + ") = " + classify(v));
|
||||
}
|
||||
Check.that(classify(0).equals("zero") && classify(-7).startsWith("negative"), "long switch dispatches on constants, then patterns");
|
||||
}
|
||||
|
||||
/** switch over an Object: primitive patterns match the boxed types they correspond to. */
|
||||
static String describe(Object o) {
|
||||
return switch (o) {
|
||||
case int i when i > 1000 -> "a large int " + i;
|
||||
case int i -> "an int " + i;
|
||||
case long l -> "a long " + l;
|
||||
case double d -> "a double " + d;
|
||||
case String s -> "a String of length " + s.length();
|
||||
default -> "something else: " + o;
|
||||
};
|
||||
}
|
||||
|
||||
static void switchOnObject() {
|
||||
System.out.println("--- switch on an Object: an Integer matches 'case int'");
|
||||
Object[] samples = {7, 5000, 7L, 2.5, "hello", 'x'};
|
||||
for (Object o : samples) {
|
||||
System.out.println("describe(" + o.getClass().getSimpleName() + " " + o + ") = " + describe(o));
|
||||
}
|
||||
Check.that(describe(5000).equals("a large int 5000"), "an Integer 5000 matches case int with a guard");
|
||||
}
|
||||
|
||||
/** Record patterns can now narrow a component: Reading.celsius is an int, the pattern asks for a byte. */
|
||||
static void recordPattern() {
|
||||
System.out.println("--- record pattern with a narrowing primitive component");
|
||||
Object[] readings = {new Reading(36), new Reading(4_000)};
|
||||
for (Object o : readings) {
|
||||
String verdict = switch (o) {
|
||||
case Reading(byte c) -> "fits in a byte: " + c;
|
||||
case Reading(int c) -> "needs a full int: " + c;
|
||||
default -> "not a reading";
|
||||
};
|
||||
System.out.println(o + " -> " + verdict);
|
||||
}
|
||||
Check.that(readings[0] instanceof Reading(byte _) && !(readings[1] instanceof Reading(byte _)),
|
||||
"Reading(byte c) matches 36 but not 4000");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user