Add sealed module: modelling domains with sealed types and exhaustive switch
Payment model, permits and the three modifiers, default-branch trap, generic and recursive hierarchies, visitor comparison, run-time enforcement, modules. Transcripts from JDK 21, 25 and 27. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01TF9JWFvJSNm6HVzswzZU5a
This commit is contained in:
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sealed classes and interfaces: permits rules, exhaustive switch without default, the traps around them, and what the JVM enforces at run time.
|
||||
# Regenerates every file in output/. JDK25=/path JDK27=/path [JDK21=/path] ./run.sh
|
||||
set -uo pipefail
|
||||
unset JAVA_TOOL_OPTIONS
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
JDK25="${JDK25:-/opt/jdks/jdk-25.0.4.1+1}"; JDK27="${JDK27:-/opt/jdks/jdk27}"; JDK21="${JDK21:-}"
|
||||
OUT="$HERE/output"; mkdir -p "$OUT"; B="$(mktemp -d)"; trap 'rm -rf "$B"' EXIT
|
||||
cd "$HERE"
|
||||
t() { "$1/bin/java" -version 2>&1 | sed -n 2p | sed 's/.*(build \(.*\))/\1/'; }
|
||||
mk() { mktemp -d -p "$B"; }
|
||||
# compile + run
|
||||
cr() { local jdk="$1" src="$2" cls="$3" o; o="$(mk)"
|
||||
echo "\$ javac $src && java $cls ($(t "$jdk"))"
|
||||
"$jdk/bin/javac" -d "$o" "$src" 2>&1 && "$jdk/bin/java" -cp "$o" "$cls" 2>&1; }
|
||||
# compile only, show diagnostics
|
||||
co() { local jdk="$1" src="$2" o; o="$(mk)"
|
||||
echo "\$ javac $src ($(t "$jdk"))"
|
||||
"$jdk/bin/javac" -d "$o" "$src" 2>&1 | grep -v '^Note:'; }
|
||||
all3() { local fn="$1"; shift; [ -n "$JDK21" ] && { "$fn" "$JDK21" "$@"; echo; }; "$fn" "$JDK25" "$@"; echo; "$fn" "$JDK27" "$@"; }
|
||||
|
||||
# 01 - the payment model
|
||||
{ all3 cr src/PaymentDemo.java PaymentDemo; } > "$OUT/01-payment-demo.txt"
|
||||
|
||||
# 02 - permits, the three modifiers, reflection and the class-file attribute
|
||||
{ all3 cr src/Reflect.java Reflect; echo; all3 cr src/ImplicitPermits.java ImplicitPermits; echo
|
||||
o="$(mk)"; "$JDK25/bin/javac" -d "$o" src/PaymentDemo.java
|
||||
echo "\$ javap -v -cp . 'PaymentDemo\$Payment' | grep -A3 PermittedSubclasses ($(t "$JDK25"))"
|
||||
"$JDK25/bin/javap" -v -cp "$o" 'PaymentDemo$Payment' | grep -A3 '^PermittedSubclasses'; } > "$OUT/02-permits-and-modifiers.txt"
|
||||
|
||||
# 03 - the compile errors, one file each
|
||||
{ for f in WalletNotHandled NotPermitted MissingModifier NoSubclass NonSealedWrongPlace AnonymousSealed; do all3 co broken/$f.java; echo; done
|
||||
xp() { local jdk="$1" o; o="$(mk)"; echo "\$ javac broken/xpkg/a/Base.java broken/xpkg/b/Impl.java ($(t "$jdk"))"
|
||||
"$jdk/bin/javac" -d "$o" broken/xpkg/a/Base.java broken/xpkg/b/Impl.java 2>&1; }
|
||||
all3 xp; } > "$OUT/03-compile-errors.txt"
|
||||
|
||||
# 04 - a default branch turns the check off
|
||||
{ all3 cr src/WithDefault.java WithDefault; } > "$OUT/04-default-trap.txt"
|
||||
|
||||
# 05 - generic and recursive hierarchies
|
||||
{ all3 cr src/ResultDemo.java ResultDemo; echo; all3 cr src/ExprDemo.java ExprDemo; } > "$OUT/05-generic-and-recursive.txt"
|
||||
|
||||
# 06 - the visitor, before sealed types
|
||||
{ all3 cr src/VisitorVersion.java VisitorVersion; echo; all3 co broken/VisitorAdded.java; } > "$OUT/06-visitor.txt"
|
||||
|
||||
# 07 - what the JVM enforces at run time (a class file whose permits clause was different when it was compiled)
|
||||
rt() { local jdk="$1" o; o="$(mk)"; mkdir "$o/v1" "$o/evil"
|
||||
"$jdk/bin/javac" -d "$o/v1" sep/v1/*.java sep/Main.java 2>&1; "$jdk/bin/javac" -d "$o/evil" sep/evil/*.java 2>&1
|
||||
cp "$o/evil/Hack.class" "$o/v1/"
|
||||
echo "\$ java -cp v1+Hack.class Main (Hack was compiled against a Payment that permitted it) ($(t "$jdk"))"
|
||||
"$jdk/bin/java" -cp "$o/v1" Main 2>&1 | head -3; }
|
||||
{ all3 rt; } > "$OUT/07-runtime-enforcement.txt"
|
||||
|
||||
# 08 - sealed across packages needs a named module
|
||||
mm() { local jdk="$1" o; o="$(mk)"
|
||||
echo "\$ javac -d out \$(find multi/demo.pay -name '*.java') && java -p out -m demo.pay/pay.app.Main ($(t "$jdk"))"
|
||||
"$jdk/bin/javac" -d "$o" $(find multi/demo.pay -name '*.java') 2>&1 && "$jdk/bin/java" -p "$o" -m demo.pay/pay.app.Main 2>&1; }
|
||||
{ all3 mm; } > "$OUT/08-modules.txt"
|
||||
echo done
|
||||
Reference in New Issue
Block a user