Java
AdventCalendar
JDK12
JavaDay 14

3分で分かった気になれるJDK12

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

https://openjdk.java.net/projects/jdk/12/

本記事では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文が不要

かなりスッキリ:relaxed:


変数への代入ケース

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に書けば解決:rolling_eyes:(てバカ

ではなく、defualtを書いておけばビルド成功します。

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」オプションをつけないとエラーになります。