defaultなしの網羅的switch
コンパイラがsealedのサブタイプをすべてカバーしているか検証 — defaultは不要。
コード比較
✕ Java 8
// Must add default even though
// all cases are covered
double area(Shape s) {
if (s instanceof Circle c)
return Math.PI * c.r() * c.r();
else if (s instanceof Rect r)
return r.w() * r.h();
else throw new IAE();
}
✓ Java 21+
// sealed Shape permits Circle, Rect
double area(Shape s) {
return switch (s) {
case Circle c ->
Math.PI * c.r() * c.r();
case Rect r ->
r.w() * r.h();
}; // no default needed!
}
このコードに問題がありますか? お知らせください。
モダンな方法が優れている理由
コンパイル時の安全性
新しいサブタイプを追加すると、コンパイラが更新が必要なすべての箇所を示します。
デッドコードなし
バグを隠すような到達不能なdefaultブランチがなくなります。
代数的型
sealed + records + 網羅的switch = JavaにおけるADT。
旧来のアプローチ
必須のdefault
モダンなアプローチ
sealedによる網羅性
JDKバージョン
21
難易度
中級
JDKサポート
defaultなしの網羅的switch
利用可能
JDK 21 LTS(2023年9月)以降、広く利用可能
仕組み
sealedな型に対してswitchを行う場合、コンパイラはすべてのサブタイプを把握し、すべてのケースが処理されているかを検証します。新しいサブタイプを追加すると、コンパイラが未対応のすべてのswitchを指摘します。
関連ドキュメント