astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

JDK12で変わったswitchに触れてみる。

お久しぶりです。開発部のyanagitaです。
4月に入り新社会人になられた方や新しい職場に移られた方、多くの職場で新たな出会いがあったのではないでしょうか?
アスタミューゼでは事業拡大に伴い、多くのエンジニア&デザイナーとの出会いを求めてます!

話を戻して、
今回は2019/03/19に正式リリースされたJDK12のswitchの新機能に触ってみたい思います。

switch文の新機能

switch文の新機能は大きく3つあります。

  • case句の複数条件の表記改善
  • break句の省略
  • switch文の式として利用

その前に

今回JDK12で公開されたswitch文の新機能はすべてプレビュー機能に分類されます。 switchの新機能を含むソースコードのコンパイル、実行、jshell上でプレビュー機能を使用するには--enable-previewオプションをつけてあげる必要があります。

コンパイル時

$ javac --enable-preview -source 12 Sample.java

コンパイル時は "--enable-preview" に合わせて "-source 12" が必要になります。(12はjdkバージョン)

実行時

$ java --enable-preview Sample

jshell起動時

$ jshell --enable-preview

※ 本記事ではjavaコマンドでjavaファイルを直接実行します。

case句の複数条件の表記改善

これまでswitch文で複数条件をマッチさせる場合、case句を条件分宣言する必要がありました。
慣れてしまうとそういうものだと思ってしまいますが、条件が増えてくるとcase句を多量に書かなくてはならず、スマートな記述が出来ていませんでした。
■ 従来のswitch文

public class SwitchSample {
    public static void main(String args[]) {
       switch (args[0]) {
           case "red" :  // マッチ条件だけcase句を記述する
           case "green" :
           case "blue" : System.out.printf("%sは色です。\n", args[0]); break;
           default : System.out.printf("条件に一致しません。[%s]\n", args[0]); break;
       }
    }
}

実行結果

$ java SwitchSample.java red
$ redは色です。
$ java SwitchSample.java blue
$ buleは色です。
$ java SwitchSample.java cat
$ 条件に一致しません。[cat]

新機能では、複数条件を1つのcase句にカンマ区切りで定義することが出来ます。

■ 新機能で書いたswitch文

public class SwitchSample {
    public static void main(String args[]) {
       switch (args[0]) {
           // マッチ条件をカンマ区切りで記述する
           case "red", "green", "blue" : System.out.printf("%sは色です。\n", args[0]); break;
           default : System.out.printf("条件に一致しません。[%s]\n", args[0]); break;
       }
    }
}

実行結果

$ java --enable-preview --source 12 SwitchSample.java red
$ redは色です。
$ java --enable-preview --source 12 SwitchSample.java blue
$ buleは色です。
$ java --enable-preview --source 12 SwitchSample.java cat
$ 条件に一致しません。[cat]

行数も減り、だいぶスッキリしました。

break句の省略

これまで条件にマッチしたcase句のみを実行する場合、case句の終わりにbleak句を記述してあげる必要がありました。新機能ではこのbreak句を省略することが可能になります。
省略する際は、これまでのcase 条件 :と記述していたところをcase 条件 ->とcase句の締めを「:」から「->」変更します。
■ 新機能で書いたswitch文

public class SwitchSample {
    public static void main(String args[]) {
       switch (args[0]) {
           case "red", "green", "blue" -> System.out.printf("%sは色です。\n", args[0]); // break; ← 省略
           default -> System.out.printf("条件に一致しません。[%s]\n", args[0]);  // break; ← 省略
       }
    }
}

ここで2点注意があります。

  1. break句の省略形式(case 条件 ->)と従来のcase句の形式を混在させたswithc文はコンパイルエラーとなるため、break句の省略を採用した場合はすべてのcase句でbreak省略形式で記述する必要があります。
  2. break句の省略形式で記述した場合、switch文内でreturnを使用することはできずコンパイルエラーとなります。

2はあまりないケースだと思いますが、修正される場合はお気をつけください。

switch文の式として利用

Scalaなどでifやmatchなど使っていると値を戻すことが当たり前になっているので、久しぶりにjavaに触れるとswitch文の手前で変数宣言をしてあげる必要があり、改めて面倒に感じることが多かったのですが、新機能ではswitch文を処理結果を返す式として扱うことができるようになります。

■ 従来のswitch文

public class SwitchSample {
    public static void main(String args[]) {
        String result = null; // switch文より前で値を受け取る変数を宣言する必要がありました。
        switch (args[0]) {
            case "red" :
            case "green" :
            case  "blue" : result = String.format("%sは色です。\n", args[0]); break;
            default : result = String.format("条件に一致しません。[%s]\n", args[0]); break;
        }
        System.out.print(result);
    }
}

■ 新機能で書いたswitch文

public class SwitchSample {
    public static void main(String args[]) {
        // switch文内の処理結果を受け取れるようになります。
        String result = switch (args[0]) {
            case "red" :
            case "green" : 
            case "blue" : break String.format("%sは色です。\n", args[0]); 
            default : break String.format("条件に一致しません。[%s]\n", args[0]);
        }; // ← switch文が式扱いになるため、「;」で終わること
        System.out.print(result);
    }
}

従来の記述に比べ、switch文が式化したことで変数への代入が一箇所にまとまり代入漏れが減るように感じます。
ここでは注意が3点あり、

  1. 値を返すのは「return 値」ではなく、「break 値」になります。returnを使用するとコンパイルエラーになります。
  2. 戻す型は、switch文から代入する変数の型のみとなります。それ以外の型になっているとコンパイルエラーとなります。
  3. 例のコメントアウトにもありますが、switch文を式として扱うため、switch文の終わりに「;」が必要となります。

全機能使用すると

■ switchの新機能を全部盛り込むと

public class SwitchSample {
    public static void main(String args[]) {
        // 従来の複数マッチ 
        String result = switch (args[0]) {
            case "red", "green", "blue" -> String.format("%sは色です。\n", args[0]);
            default -> String.format("条件に一致しません。[%s]\n", args[0]);
        };
        System.out.print(result);
    }
}

switch文がすごいスッキリしたと思います。個人的には式対応したことはすごく嬉しいです。

おまけ

従来のswitch文と新機能のswitch文で処理速度を比較してみました。
が!差は全くありませんでした。ネタにならず・・・

最後にもう一度

アスタミューゼではたくさんのエンジニア&デザイナをまだまだまだ募集しています。 気になる方は下からご応募下さい!新しい出会いをメンバー一同お待ちしてます!

Copyright © astamuse company, ltd. all rights reserved.