CodeZine(コードジン)

特集ページ一覧

Java 12~15でリリースされた機能を確認しよう! 新しいクラス・構文・式でコードが書きやすく

Java 12からJava 15までの変更点を確認しよう 第1回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2020/09/28 11:00

 Java 11(LTS)バージョンがリリースされてから、約2年がたち、2020年9月にJava 15がリリースされました。また、約1年後にはJava 17という次のLTSバージョンがリリースされようとしています。そこで今回は、次のLTSバージョンを見据えてJava 14からJava 15に含まれた機能をご紹介します。

目次

Java 12からJava 15までの言語仕様・API変更点

 Java 12からJava 15では、Project Amberというプロジェクトに関連する変更が多く含まれています。このプロジェクトは、Javaのソースコードの可読性を高め、バグが生じにくいコードを記述できるようにすることを目的としています。その中から今回はプレビュー版としてもリリースされたものも含め、表1について紹介致します。

                 
表1:Java 14、Java 15で追加・変更された言語仕様
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のようなコードを記述していました。

[リスト1]これまでのswitch表現(src/main/java/jp/enbind/jdk15/Jep361.javaからの抜粋)
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の通り記述できるようになりました。コードから開発者はより直感的に何をしているのかがわかりやすくなったと思います。

[リスト2] 新しいSwitch表現を使った場合の例(src/main/java/jp/enbind/jdk15/Jep361.javaからの抜粋)
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表現に書き換えることができません。

[リスト3] breakを意図的に使わない場合のSwitch表現例(src/main/java/jp/enbind/jdk15/Jep361.javaからの抜粋)
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のようにかなり簡素に記述できるようになりました。

[リスト4] 値(文字列)を返す場合のSwitch式のコード例(src/main/java/jp/enbind/jdk15/Jep361.javaからの抜粋)
String ret = switch (val){
    case 1 -> "one";
    case 2 -> "two";
    default -> "unknown";
}

 このコードは、以下のリスト5を簡略したものです。明示的に返す値を指定する場合には、yieldを利用します。

[リスト5] 明示的に値(文字列)を返す場合のSwitch式のコード例(src/main/java/jp/enbind/jdk15/Jep361.javaからの抜粋)
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のようなコードを記述していました。

[リスト6] 従来のJavaで複数行文字列を記述した場合(src/main/java/jp/enbind/jdk15/Jep378.javaからの抜粋)
String html  = "<html lang=\"ja\">\n" +
               "   <body>\n" +
               "      Hello World\n" +
               "   </body>\n" +
               "</html>";

 ダブルクォートやエスケープシーケンスが混在しており、文字列の見通しがよくありません。

 しかし、Java 15からはリスト6のように「"""(ダブルクォート3個)」でくくった文字列リテラルを表現できるようになりました(Text Blocks)。Text Blocksを利用することで、先ほどのコードを以下のように書き換えられます。

[リスト7] Text Blocksを使った場合(src/main/java/jp/enbind/jdk15/Jep378.javaからの抜粋)
String html = """
        <html lang="ja">
          <body>
            Hello World
          </body>
        </html>
        """;

 改行含みの文字列を(エスケープシーケンスなしに)そのまま記述できる点、途中に「ダブルクォート(")」を含む場合でも、エスケープすることなく、そのまま記述できる点に注目です。

 図1のように各行頭の空白も文字列内のインデントは維持した状態で、不要な部分だけが削除されるので、記述者の意図通りの文字列を表現できます。

図1:Text Blocksで保持される空白と削除される空白
図1:Text Blocksで保持される空白と削除される空白

Text Blocksから改行を除去する

 一方、Text Blocksの改行を無視したい場合もあります。その場合には、リスト8のように行末にバッククォート(\)を指定します。

[リスト8] 改行コードを意図的に含めたくない場合(src/main/java/Jep378.javaからの抜粋)
String sql = """
        SELECT * \
        FROM category \
        WHERE type = 'post' \
        AND group = 'news'\
        """;

 これは「SELECT * FROM category WHERE type = 'post' AND group = 'news'」と同じ意味です。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしど...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

バックナンバー

連載:Java 12からJava 15までの変更点を確認しよう
All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5