Java 12からJava 15までの言語仕様・API変更点
Java 12からJava 15では、Project Amberというプロジェクトに関連する変更が多く含まれています。このプロジェクトは、Javaのソースコードの可読性を高め、バグが生じにくいコードを記述できるようにすることを目的としています。その中から今回はプレビュー版としてもリリースされたものも含め、表1について紹介致します。
JEP | 名称 | リリースされたバージョン |
---|---|---|
JEP361 | Switch Expressions - Switch表現の拡張 | Java14(Java 12でプレビュー版) |
JEP378 | Text Blocks | Java15(Java 13でプレビュー版) |
JEP375 | Pattern Matching for instanceof | Java15(プレビュー版) |
JEP384 | Records | Java14(プレビュー版) |
JEP360 | Sealed Classes | Java15(プレビュー版) |
Switch Expressions - switch表現の拡張
Java 14では、switch命令が改善され、case句でラムダ式を利用できるようになったり、switchそのものが式として利用できるようになっています。今回の改善によって、switchが記述しやすく、そして間違いを抑えやすくなりました。以下では、具体的なサンプルと変更点を順に見ていきます。
break文が省略できるラムダ形式での記述方法
これまでswitch文を記述する際には、リスト1のようなコードを記述していました。
switch (val){ case 1 : System.out.println("one"); break; case 2: System.out.println("two"); break; default: System.out.println("unknown"); break; }
このようなコードでよくうっかりミスとして行ってしまいがちなのが、switch-case句の最後にbreakを忘れてしまうことです。開発者の中には毎回breakを記述しているのだから、breakを省略できないだろうかと思う方もいるようです。
そこでJava 14からは、リスト2の通り記述できるようになりました。コードから開発者はより直感的に何をしているのかがわかりやすくなったと思います。
switch (val){ //(1)基本的な記述 case 1 -> System.out.println("one"); case 2 -> System.out.println("two"); //(2) 複数のケースにも対応 case 3 ,4 -> System.out.println("three or four"); // (3) 複数行を記述する場合 default -> { System.out.println("value is ...."); System.out.println("unknown"); } };
これまで、コロン(:)で分けていましたが、新しいswitch表現では、ラムダ形式(->)で記述します((1))。また、複数の値に一致した場合を表現する場合には、(2)のようにcase句にカンマ区切りの値を列挙できます。さらに、(3)のように波括弧({})を使うことで、複数行を記述することも可能です。
ただし、今までのコロン「:」を使った形式が使えなくなったわけではなく、また、完全に置き換え可能な記述方式ではありません。
例えば、リスト3のように、意図的にbreakを使わない場合を想定してみましょう。このような使い方では、新しいswitch表現に書き換えることができません。
private void networkDataRead(int type, InputStream in) throws IOException{ byte bytes[] = new byte[4096]; switch (type){ case 1 : in.skip(20); // 20byteスキップした後、次のcase句を処理 case 2: in.read(bytes,0,4); this.tokenCase = 4; break; case 3: // 省略 } }
値を返すswitch式
switch表現は文としてではなく、式としても利用できるようになりました。つまり、値を返すことが可能になっています。各パターンに合わせた値を返すようなコードはリスト4のようにかなり簡素に記述できるようになりました。
String ret = switch (val){ case 1 -> "one"; case 2 -> "two"; default -> "unknown"; }
このコードは、以下のリスト5を簡略したものです。明示的に返す値を指定する場合には、yieldを利用します。
String ret = switch(val){ case 1 : yield "one"; case 2 : yield "two"; default: yield "unknown"; };
これまでのswitch文では、breakやdefaultを記述することを忘れるなどでバグにつながったりすることがあります。しかし、新しいswitch式として利用する場合にはbreakの記述もいらず、またdefaultは必須になるので、そのようなミスが発生しにくくなります。
Text Blocks - 改行などを含むテキスト表記の可読性を向上
Javaのコード内に書かれたSQL、HTMLなどのコードは、往々にして読みにくいものです。例えば、従来はリスト6のようなコードを記述していました。
String html = "<html lang=\"ja\">\n" + " <body>\n" + " Hello World\n" + " </body>\n" + "</html>";
ダブルクォートやエスケープシーケンスが混在しており、文字列の見通しがよくありません。
しかし、Java 15からはリスト6のように「"""(ダブルクォート3個)」でくくった文字列リテラルを表現できるようになりました(Text Blocks)。Text Blocksを利用することで、先ほどのコードを以下のように書き換えられます。
String html = """ <html lang="ja"> <body> Hello World </body> </html> """;
改行含みの文字列を(エスケープシーケンスなしに)そのまま記述できる点、途中に「ダブルクォート(")」を含む場合でも、エスケープすることなく、そのまま記述できる点に注目です。
図1のように各行頭の空白も文字列内のインデントは維持した状態で、不要な部分だけが削除されるので、記述者の意図通りの文字列を表現できます。
Text Blocksから改行を除去する
一方、Text Blocksの改行を無視したい場合もあります。その場合には、リスト8のように行末にバッククォート(\)を指定します。
String sql = """ SELECT * \ FROM category \ WHERE type = 'post' \ AND group = 'news'\ """;
これは「SELECT * FROM category WHERE type = 'post' AND group = 'news'」と同じ意味です。