Java 17 の 9/14 リリースを目前に Oracle が新機能などを紹介したブログ記事を公開

投稿: 2021年09月13日
タグ: 
  Developer(Java等)  ニュースネタ

Java 17 が 2021/09/14 に一般提供(General Availability) されます。 Java 17 は Java 8、Java 11 に続く LTS (Long Term Support) バージョンであるため、多くのユーザーの将来の移行先バージョンであると想定されています。
Oracle 社はリリースに先立ち、Java Magazine で Java 17 の新機能に関する記事を投稿しました。

リリースは 9/14 ですが、リリースノートや APIリファレンスなど技術文書は既に公開されています。
Java 17 は 14個の JEP(JDK拡張提案) が含まれており、前述の記事では言語自体の改善である「Sealed Class (JEP 409)」や コアライブラリのアップグレードである「コンテキスト固有のデシリアライズフィルター (JEP415)」等について紹介されています。
また、プレビュー機能である「switch 文に対するパターンマッチ (JEP 406)」についても紹介されています。

Java 17 で正式リリースされる Sealed Class(シール・クラス)

シール・クラスは JDK 15 の時点でプレビュー機能として登場し、JDK 16 でもプレビュー機能として改善された後、JDK 17 で正式リリースとなっています。JDK 16 からは変更されずにリリースされます。

シール・クラスの説明は日本語で以下のドキュメントが公開されています。

Java SE 16 - Java言語更新 - 3 シール・クラス
https://docs.oracle.com/javase/jp/16/language/sealed-classes-and-interfaces.htmlopen_in_new

シール・クラスは簡単に言うと『クラスやインタフェースの継承先を明示的に制限する』機能になります。
例えば、以下実装の場合、Animal インタフェースは Bird クラスでのみ実装できます。Animal インタフェースを Fish クラスや Human クラスを実装しようとするとエラーになります。

Java 17
public sealed interface Animal permits Bird { }

シール・クラスの JEP には、シール・クラス導入の動機付けとして以下のように記載されています。

it should be possible for a superclass to be widely accessible (since it represents an important abstraction for users) but not widely extensible (since its subclasses should be restricted to those known to the author)

スーパークラスは広くアクセス可能であるべきだが(ユーザーにとって重要な抽象化を実現するため)、広く拡張可能であるべきではない(サブクラスは親クラスの開発者が認識しているものに制限させるため)。

シール・クラスは親クラス・インタフェースで子クラスを指定するため、これまでの「子は親を知っているが、親は子を(基本的には) 知らない」から「親も(明示的に) 子を知っている」関係ができます。
シール・クラスが必要になるシーンはそれほど多くはないと思いますが(近年では、そもそも継承が必要ないような実装になっていることが多いと思います)、適切に使わないと親子間の依存関係が強く修正しにくいコードになってしまうかもしれません。 JEP の文章は以下のように続いています。

The author of such a superclass should be able to express that it is co-developed with a given set of subclasses, both to document intent for the reader and to allow enforcement by the Java compiler. At the same time, the superclass should not unduly constrain its subclasses by, e.g., forcing them to be final or preventing them from defining their own state.

スーパークラスの開発者は特定のサブクラスと一緒に開発されていることを、文書化および Javaコンパイラで強制可能にして表現すべきです。同時に、スーパークラスは、サブクラスで独自の状態を定義できない、強制的に final にする等して過度に制約すべきではありません。

Java 17 でプレビュー提供される switch パターンマッチ

現状よりも柔軟に switch-case 文を書けるようにしよう、という拡張です。JEP には以下のようなコード例が挙げられています。

Java 17
static void typeTester(Object o) { switch (o) { case null -> System.out.println("null"); case String s -> System.out.println("String"); case Color c -> System.out.println("Color with " + Color.values().length + " values"); case Point p -> System.out.println("Record class: " + p.toString()); case int[] ia -> System.out.println("Array of ints of length" + ia.length); default -> System.out.println("Something else"); } }

1つ目のポイントは引数として渡された o の型に従って分岐される点。2つ目のポイントは例え引数が null であっても switch 文の中で評価ができる点です。
これまでであれば、switch 文の前で null でないかを if 文でチェックする必要がありました。その結果、そのまま switch を使わず if-else で済ませてしまうこともあったのではないかと思います。 当該拡張で少なくとも現状よりすっきりとしたコードを書けるようになりそうです。