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

[Java Advent Calendar 2018](https://qiita.com/advent-calendar/2018/java) 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プログラマーにとって影響のある２つ

- 「325: Switch Expressions (Preview)」
- 「326: Raw String Literals (Preview)」

について解説する。

#JEP325: Switch Expressions (Preview)
Project Amberの一仕様である。Javaのswitch構文の表現を少し改善するもの。

今までのswitch構文は、break文の出現順に依存していたため直感的ではなく、それが潜在バグの元にもなってきた。

```java
//今までの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文

```java
//改善された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文でよくあるケースとして変数への代入がある。

```java
//今までの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内で代入処理を書いているが、これが以下のように書ける。

```java
//改善されたswitch文
int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY                -> 7;
    case THURSDAY, SATURDAY     -> 8;
    case WEDNESDAY              -> 9;
};
```

あと、こんな書き方もできる。

```java
int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY: break 6;
    case TUESDAY:                break 7;
    case THURSDAY, SATURDAY:     break 8;
    case WEDNESDAY:              break 9;
};
```

###エラーパターン

いくつか気をつけること

ケース１

```java
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:(てバカ
ではなく、defaultを書いておけばビルド成功します。

```java
final int num = 3;
String str = switch(num) {
    case 1 -> "one";
    case 2 -> "two";
    default -> "non";
};
```

ケース２

```java
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パスや正規表現、複数行文字列をソースコード内に書くとき、今まではいちいちエスケープしたり改行入れたりして生産性も可読性も落ちてたけど、そんな煩わしさから解放される。

「"(ダブルクォート)」ではなく、「`(バッククォート)」で文字列を囲む。

ファイルパスの例

```java
Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar");
Runtime.getRuntime().exec(`"C:\Program Files\foo" bar`);
```

正規表現の例

```java
System.out.println("this".matches("\\w\\w\\w\\w"));
System.out.println("this".matches(`\w\w\w\w`));
```
複数行の例

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