Java 14の機能

2019年9月17日にJava 13がリリースされた後、2020年3月17日にもう1つの非LTSバージョンであるJava 14がリリース予定です。

Java 14の機能

以下はJava 14の機能のリストです:

  • スイッチ式(標準)- JEP 361
  • instanceofのためのパターンマッチング(プレビュー)- JEP 305
  • 便利なNullPointerExceptions – JEP 358
  • レコード(プレビュー)- JEP 359
  • テキストブロック(セカンドプレビュー)- JEP 368
  • パッケージングツール(インキュベータ)- JEP 343
  • G1のNUMA対応メモリ割り当て – JEP 345
  • JFRイベントストリーミング – JEP 349
  • ノンボラタイルマップドバイトバッファ – JEP 352
  • macOSでのZGC – JEP 364
  • WindowsでのZGC – JEP 365
  • 外部メモリアクセスAPI(インキュベータ)- JEP 370

Mac OSでのJava 14のインストール設定

  • Java 14を始めるために、ここからJDKをダウンロードしてください。
  • 次に、次のように/Library/Java/JavaVirtualMachinesにtarファイルをコピーして展開してください:
$ cd /Library/Java/JavaVirtualMachines

$ sudo cp ~/Downloads/openjdk-14_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines

$ sudo tar xzf openjdk-14_osx-x64_bin.tar.gz

$ sudo rm openjdk-14_osx-x64_bin.tar.gz

それが完了したら、任意のテキストエディタを使用してbash_profileを開きます。私はvim ~/.bash_profileを使用しています。Java14のパスをJAVA_HOMEに設定し、変更を保存してsource ~/.bash_profileを実行して変更を反映させてください。

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home

最後に、Java 14を使用してプログラムをコンパイルして実行する準備が整いました。新しいJava 14の機能を素早くテストするための対話型REPLコマンドラインツールであるJShellを使用します。

Java 14でリリースされた多くの機能はプレビュー版であることに注意してください。これは、現在は完全に動作しているものの、将来的に変更される可能性があることを意味します。次のリリースサイクルで標準化されるか、単純に削除されることがあります。プレビュー機能をテストするためには、JShellまたはJavaプログラムを実行する際に--enable-previewを明示的に設定する必要があります。以下に示します:

jshell --enable-preview

javac --release 14 --enable-preview Author.java

次の数節では、いくつかの言語およびJVMの機能について説明します。

おすすめの読み物LinuxにJava 14をインストールする

1. スイッチ式

Java 12とJava 13は、最後の2つのリリースでプレビュー機能として提供されたスイッチ式が、ついにJava 14で正式な機能として採用されました。

  • Java 12では、スイッチ式のためのラムダ構文が導入され、パターンマッチングのために複数のケースラベルが可能となり、またフォールスルーを防ぐことで冗長なコードを防ぎました。また、全ての入力ケースがカバーされていない場合にはコンパイルエラーが発生するようになりました。
  • Java 13では、2番目のプレビューとしてyieldステートメントが導入され、breakではなく式から値を返すために使用されるようになりました。

Java 14では、これらの機能が正式なものとなりました。

String result = switch (day) {
            case "M", "W", "F" -> "MWF";
            case "T", "TH", "S" -> "TTS";
            default -> {
                if(day.isEmpty())
                    yield "Please insert a valid day.";
                else
                    yield "Looks like a Sunday.";
            }

        };
System.out.println(result);
Java 14 Switch Expressions

注意: YieldはJavaの新しいキーワードではありません。スイッチ式で使用されるだけです。

2. instanceofのためのパターンマッチング(プレビュー)

Javaの開発者にコードベースを見せてもらえば、instanceof条件の使用例がたくさんあるでしょう。特に、instanceof条件のチェックの後には、型キャストが通常続きます。

Java 14では、この冗長性を排除し、条件抽出をより簡潔に行うことができるようになりました。

Java 14より前:

if (obj instanceof Journaldev) {
  Journaldev jd = (Journaldev) obj;
  System.out.println(jd.getAuthor());
}

Java 14以降:

if (obj instanceof Journaldev jd) {
  System.out.println(jd.getAuthor());
}

上記のコードでは、jd インスタンスは objJournaldev の型である場合にのみ割り当てられます。変数のスコープは条件ブロックに限定されます。

3. 便利な NullPointerExceptions

NullPointerExceptions は、どんな開発者にとっても悪夢です。以前は、Java 13 までは有名な NPE のデバッグが難しかったです。スタックトレースには行番号しか表示されず、他のデバッグツールに頼るか、変数/メソッドが null であることを手動で特定する必要がありました。

Java 14 以前:

String name = jd.getBlog().getAuthor()

//スタックトレース
Exception in thread "main" java.lang.NullPointerException
    at NullPointerExample.main(NullPointerExample.java:5)

Java 14 では、以下のようにより詳細なスタックを提供する新しい JVM の機能が導入されました:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Journaldev.getBlog()" is null
    at NullPointerExample.main(NullPointerExample.java:4)

注意: 上記の機能は言語の機能ではありません。ランタイム環境の改善です。

4. レコード (プレビュー)

A record is a data class that stores pure data. The idea behind introducing records is to quickly create simple and concise classes devoid of boilerplate code.

通常、Java のクラスでは、equals()hashCode()、ゲッターとセッターのメソッドを実装する必要があります。一部の IDE はこのようなクラスの自動生成をサポートしていますが、コードはまだ冗長です。 record では、次のようにクラスを定義するだけで済みます。

record Author(){}
//または
record Author (String name, String topic) {}

Javaコンパイラは、コンストラクタ、private finalフィールド、アクセサ、equals/hashCode、toStringメソッドを自動生成します。上記クラスの自動生成されたgetterメソッドは、name()topic()です。

生成されたコードを確認するには、javacを使用してプログラムをコンパイルした後、javap Authorを使用します。以下のイラストは、record Author (String name, String topic) {}の生成されたクラスを示しています。

Javap Records Java 14

レコードのセマンティクスは、Kotlinのデータクラスに似ています。Data Classes in Kotlin

さらに、次のようにレコードに追加のフィールド、メソッド、およびコンストラクタを追加できます:

record Author (int id, String name, String topic) {
    static int followers;

    public static String followerCount() {
        return "Followers are "+ followers;
    }

    public String description(){
        return "Author "+ name + " writes on "+ topic;
    }

    public Author{
    if (id < 0) {
        throw new IllegalArgumentException( "id must be greater than 0.");
     }
   }
}

レコード内で定義される追加のコンストラクタは、コンパクトコンストラクタと呼ばれます。これにはパラメータは含まれず、単に正規のコンストラクタの拡張です。

A compact constructor wouldn’t be generated as a separate constructor by the compiler. Instead, it is used for validation cases and would be invoked at the start of the main constructor.

レコードに関する重要な注意事項:

  • A record can neither extend a class nor it can be extended by another class. It’s a final class.
  • レコードは抽象的にすることはできません
  • レコードは他のクラスを拡張することはできず、本体内でインスタンスフィールドを定義することはできません。インスタンスフィールドは状態記述のみで定義する必要があります。
  • 宣言されたフィールドはprivateかつfinalです。
  • レコードの本体には、静的フィールドとメソッドを記述することができます。

おすすめのリーディングJava Records

4.1) レコードの参照フィールド内の値は変更可能です

オブジェクトとして定義されたフィールドでは、参照のみが不変です。基になる値は変更可能です。次の図は、ArrayListが変更されたときに値が変更されるレコードを示しています。

Java 14 Records Mutable Values For References

4.2) レコードはインターフェースを実装できます

次のコードは、レコードでインターフェースを実装する例です:

record Author(String name, String topic) implements Information {
  public String getFullName() {
    return "Author "+ name + " writes on " + topic;
  }
}

interface Information {
  String getFullName();
}

上記のコードをJShellで実行した場合の出力は次のとおりです:

Java 14 Records With Interface

4.3) レコードは複数のコンストラクタをサポートしています

レコードでは、次のようにパラメータを持つ複数のコンストラクタを宣言することができます:

record Author(String name, String topic) {
  public Author() {

    this("NA", "NA");
  }

  public Author(String name) {

    this(name, "NA");
  }
}

4.4) レコードはアクセサメソッドの変更を許可します

レコードは、状態の定義に基づいてフィールドのためのパブリックなアクセサメソッドを生成しますが、以下のようにボディ内でアクセサメソッドを再定義することも可能です:

record Author(String name, String topic) {
  public String name() {
        return "This article was written by " + this.name;
    }
}

4.5) レコードとそのコンポーネントの実行時チェック

レコードは、isRecord()getRecordComponents() を提供し、クラスがレコードかどうか、またそのフィールドと型を調べることができます。以下の図は、その方法を示しています:

Java 14 Records Runtime Check

上記のコード例では、レコードに追加のフィールドとメソッドを追加しましたが、これを過度に行わないように注意してください。レコードは単なるデータのキャリアとして設計されており、多くの追加メソッドを実装する場合は、通常のクラスに戻る方が良いです。

5. テキストブロック(プレビュー)

テキストブロックは、Java 13でプレビュー機能として導入され、複数行の文字列リテラルの簡単な作成を可能にすることを目的としています。HTMLやJSON、またはSQLクエリ文字列の作成に便利です。

Java 14では、テキストブロックはまだプレビュー機能のままで、いくつかの新機能が追加されています。以下が使用できるようになりました:

  • バックスラッシュを使用して見栄えの良い複数行の文字列ブロックを表示するための機能。
  • \sは、デフォルトではコンパイラによって無視される末尾のスペースも考慮するために使用されます。それはそれの前に存在するすべてのスペースを保持します。
String text = """
                Did you know \
                Java 14 \
                has the most features among\
                all non-LTS versions so far\
                """;

String text2 = """
                line1
                line2 \s
                line3
                """;


String text3 = "line1\nline2 \nline3\n"

//text2とtext3は等しいです。

参考文献OpenJDK 14

Source:
https://www.digitalocean.com/community/tutorials/java-14-features