Java Advent Calendar 2018 14日目の記事です。
JDK12が来年リリースされる予定なので、12の変更内容について一部紹介します。
#Features
JDK12に含まれるJEP(JDK Enhancement Proposal)は以下
2018/12/6時点
89: Shenandoah: A Low-Pause-Time Garbage Collector
(Experimental)
230: Microbenchmark Suite
325: Switch Expressions (Preview)
326: Raw String Literals (Preview) ←JDK12からdropされるかも(2018/12/14更新)
334: JVM Constants API
340: One AArch64 Port, Not Two
341: Default CDS Archives
344: Abortable Mixed Collections for G1
346: Promptly Return Unused Committed Memory from G1
本記事ではJava構文に関する変更で多くのJavaプログラマーにとって影響のある2つ
- 「325: Switch Expressions (Preview)」
- 「326: Raw String Literals (Preview)」
について解説する。
#JEP325: Switch Expressions (Preview)
Project Amberの一仕様である。Javaのswitch構文の表現を少し改善するもの。
今までのswitch構文は、break文の出現順に依存していたため直感的ではなく、それが潜在バグの元にもなってきた。
//今までのswitch文
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}
以下は改善されたswitch文
//改善されたswitch文
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
- caseのラベルが複数書ける
- ->でラムダ式のように書ける
- break文が不要
かなりスッキリ
###変数への代入ケース
switch文でよくあるケースとして変数への代入がある。
//今までのswitch文
int numLetters;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numLetters = 6;
break;
case TUESDAY:
numLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numLetters = 8;
break;
case WEDNESDAY:
numLetters = 9;
break;
default:
throw new IllegalStateException("Wat: " + day);
}
いちいち各case内で代入処理を書いているが、これが以下のように書ける。
//改善されたswitch文
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
あと、こんな書き方もできる。
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY: break 6;
case TUESDAY: break 7;
case THURSDAY, SATURDAY: break 8;
case WEDNESDAY: break 9;
};
###エラーパターン
いくつか気をつけること
ケース1
final int num = 3;
String str = switch(num) {
case 1 -> "one";
case 2 -> "two";
};
この書き方はコンパイルエラーになる。
エラーメッセージは「the switch expression does not cover all possible input values」
つまり、switchの引数が取りうる値は全てswitchの条件分岐としてカバーしろよ!ということ。
この場合は、intの取りうる値を全てcaseに書けば解決(てバカ
ではなく、defaultを書いておけばビルド成功します。
final int num = 3;
String str = switch(num) {
case 1 -> "one";
case 2 -> "two";
default -> "non";
};
ケース2
final int num = 3;
String str = switch(num) {
case 1: break "one";
case 2 -> "two";
default -> "non";
};
これもコンパイルエラーになる。
エラーメッセージは「different case kinds used in the switch」
書き方を統一しろや!てこと。
#326: Raw String Literals (Preview)
文字列リテラルの表現がシンプルになる。
URLパスや正規表現、複数行文字列をソースコード内に書くとき、今まではいちいちエスケープしたり改行入れたりして生産性も可読性も落ちてたけど、そんな煩わしさから解放される。
「"(ダブルクォート)」ではなく、「`(バッククォート)」で文字列を囲む。
ファイルパスの例
Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar");
Runtime.getRuntime().exec(`"C:\Program Files\foo" bar`);
正規表現の例
System.out.println("this".matches("\\w\\w\\w\\w"));
System.out.println("this".matches(`\w\w\w\w`));
複数行の例
String html = "<html>\n" +
" <body>\n" +
" <p>Hello World.</p>\n" +
" </body>\n" +
"</html>\n";
String html = `<html>
<body>
<p>Hello World.</p>
</body>
</html>
`;
#最後に
どちらもPreviewステータスなので、今後変更が入ることもあるかもしれませんし、実際の本番(業務)で使えるのはJDK13以降になると思います。なのでJDK12では触れて遊ぶ程度に楽しんでください。
あと、コンパイルと実行時には「--enable-preview」オプションをつけないとエラーになります。