LoginSignup
5
5

More than 3 years have passed since last update.

Java 14で最低限押さえておきたい新機能をEclipseで使ってみた

Last updated at Posted at 2020-03-22

はじめに

2020/3/17にJava 14がリリースされました。
以下の機能が追加されたようです。
下の表の「本記事の対象」列に〇がついているものを少し触ってみたので後で紹介します。

JEP(※1) 概要 本記事の対象
305 Pattern Matching for instanceof (Preview)(※2)
343 Packaging Tool (Incubator)(※3) ×
345 NUMA-Aware Memory Allocation for G1 ×
349 JFR Event Streaming ×
352 Non-Volatile Mapped Byte Buffers ×
358 Helpful NullPointerExceptions
359 Records (Preview)
361 Switch Expressions (Standard)
362 Deprecate the Solaris and SPARC Ports ×
363 Remove the Concurrent Mark Sweep (CMS) Garbage Collector ×
364 ZGC on macOS ×
365 ZGC on Windows ×
366 Deprecate the ParallelScavenge + SerialOld GC Combination ×
367 Remove the Pack200 Tools and API ×
368 Text Blocks (Second Preview)
370 Foreign-Memory Access API (Incubator) ×

公式はこちら

※1 JEP
JDK Enhancement Proposalsの略。
JDKに対する変更の提案を管理する番号。

参考:https://www.slideshare.net/AyaEbata/jsrjepjbs
JEPの目次:https://openjdk.java.net/jeps/0

※2 Preview
プレビュー版のこと。
機能としては保証されているが、どのように使うべきかは議論の余地があるもの。開発者が実際に使ってみて、フィードバックを受けて今後もJava SEの基本機能として提供し続けるかどうかが決まる。

※3 Incubator
開発者からのフィードバックを得るために、Java SEに含めた実験的なAPI。

参考:https://xtech.nikkei.com/it/atcl/column/15/120700278/080700044/

Java 14をEclipseで使えるようにするための設定

私はEclipse使いなので、JDK 14のインストールとEclipseの設定から始めます。

JDKダウンロード

以下のサイトからJDK14をダウンロードします。
https://www.oracle.com/java/technologies/javase-downloads.html

Eclipseインストール

Eclipseの最新版をインストールします。
https://www.eclipse.org/eclipseide/

EclipseでJDK14を扱えるようにする

EclipseでJDK14を扱えるようにする手順は以下の通り。

①Eclipse Marketplaceを選択

②Java 14 Support for Eclipse をインストール

※こういったEclipse本体やプラグインのリリース情報は公式のtwitterからも流れてくるので興味ある方はフォローすることをお勧めします。



③Compiler compliance levelを14に設定
※Java 14 Support for Eclipse をインストールしないと14が選択肢に出ません。

④Installed JREに、インストールしたJDK14を設定

⑤Execution emvironmentにJDK14を設定

⑥今回はプレビューの機能も使うので、プレビューを有効化します。

これでJava 14を使ったJavaアプリケーションをEclipseで開発・実行できるようになります。

Java 14の新機能を触ってみる

早速触ってみました。

JEP 305:Pattern Matching for instanceof (Preview)

まずはJEP 305のPattern Matching for instanceofです。
instanceof と同時に変数を定義できるようになりました。
実際の書き方の例は以下の通りです。
前半がこれまでの書き方、後半がPattern Matching for instanceofを使用した書き方になっています。

まずはこれまでの書き方。

NotPatternMatchingTest.java
public class NotPatternMatchingTest {
    public static void main(String... args) {
        patternMatch("literal");
        patternMatch(1);

    }

    private static void patternMatch(Object obj) {
        // これまでの書き方
        if (obj instanceof String) {
            String str = (String) obj;
            System.out.println("No Pattern Matching:" + str);
        } else if (obj instanceof Integer) {
            Integer inte = (Integer) obj;
            System.out.println("No Pattern Matching:" + inte);
        }
    }
}

これがPattern Matching for instanceof を使用した書き方。

PatternMatchingTest.java
public class PatternMatchingTest {
    public static void main(String... args) {
        patternMatch("literal");
        patternMatch(1);
    }

    // previewなのでSuppressWarningsでワーニング抑止
    @SuppressWarnings("preview")
    private static void patternMatch(Object obj) {
        // Pattern Matching for instanceof
        if (obj instanceof String str) {
            System.out.println("Pattern Matching:" + str);
        } else if (obj instanceof Integer inte) {
            System.out.println("Pattern Matching:" + inte);
        }
    }
}

switch文での使用はJava 15以降に持ち越しになっているようです。
http://openjdk.java.net/jeps/8213076

JEP 358:Helpful NullPointerExceptions

NullPointerExceptionが発生した場合のメッセージが詳細になり、原因を特定しやすくなりました。
-XX:+ShowCodeDetailsInExceptionMessagesオプションをつけて実行することで、詳細なメッセージを得ることができます。
以下のサンプルコードで実験してみました。

HelpfulNullPo.java
public class HelpfulNullPo {
    public static void main(String... args) {
        String str = null;
        str.length();
    }
}

-XX:+ShowCodeDetailsInExceptionMessagesオプションを付けずに実行した結果がこちら。

実行結果(オプションなし)
Exception in thread "main" java.lang.NullPointerException
    at test.HelpfulNullPo.main(HelpfulNullPo.java:6)

-XX:+ShowCodeDetailsInExceptionMessagesオプションをつけて実行した結果がこちら。

実行結果(オプション有)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "str" is null
    at test.HelpfulNullPo.main(HelpfulNullPo.java:6)

NullPointerExceptionの原因特定がしやすくなっています。

なお、JShellの場合は-R-XX:+ShowCodeDetailsInExceptionMessagesという指定になります。

JEP 359:Records (Preview)

データ保持用のクラスとしてrecordという機能がpreviewとして入りました。
以下のように書くだけでデータ保持用のクラスを作ることができます。
record Person(String name, int age) {}の部分)

RecordTest.java
@SuppressWarnings("preview")
record Person(String name, int age) {}

public class RecordTest {
    public static void main(String... args) {
        Person person = new Person("taumax", 13);
        System.out.println("name:" + person.name());
        System.out.println("age:" + person.age());
        System.out.println(person);
    }
}
実行結果
name:taumax
age:13
Person[name=taumax, age=13]

インスタンス生成後に値を変更することはできないようです。
厳密には違いますが、イメージ的にはイミュータブルなJavaBeansを簡単に作ることができるようになったという感覚ですかね。

JEP 361:Switch Expressions (Standard)

Switch文がアロー->を使って書けるようになり、かなり読みやすくなりました。また、breakの記載も不要になっています。
Switch ExpressionsはJava 12でプレビューとして導入されたものですが、今回のJava 14で正式機能として導入されます。
実際の書き方の例は以下の通りです。
前半がこれまでの書き方、後半がSwitch Expressionsを使用した書き方になっています。

まずはこれまでのswitch文

OldSwitchExpressions
public class OldSwitchExpressions {
    public static void main(String... args) {
        for (Week day : Week.values()) {
            oldSwitch1(day);
        }
    }

    // これまでのswitch文
    private static void oldSwitch1(Week day) {
        System.out.print("old:");
        switch (day) {
            case MONDAY, FRIDAY, SUNDAY:
                System.out.println(6);
                break;
            case TUESDAY:
                System.out.println(7);
                break;
            case THURSDAY, SATURDAY:
                System.out.println(8);
                break;
            case WEDNESDAY:
                System.out.println(9);
                break;
        }
    }

    private enum Week {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY
    }
}

これがSwitch Expressions

SwitchExpressions
public class SwitchExpressions {
    public static void main(String... args) {
        for (Week day : Week.values()) {
            newSwitch1(day);
        }
    }

    // 新しいswitch文
    private static void newSwitch1(Week day) {
        System.out.print("new:");
        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);
        }
    }

    private enum Week {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY
    }
}

アロー->を使い、breakがなくなったことでかなり可読性が高くなったことがわかります。

また、switch文の実行結果をそのまま変数に代入することができるようになりました。
実際の書き方の例は以下の通りです。
前半がこれまでの書き方、後半がSwitch Expressionsを使用した書き方になっています。
まずはこれまでの書き方。

OldSwitchExpressions2
public class OldSwitchExpressions2 {
    public static void main(String... args) {
        for (Week day : Week.values()) {
            oldSwitch2(day);
        }
    }

    // これまでのswitch文
    private static void oldSwitch2(Week day) {
        System.out.print("old:");
        int numLetters;
        switch (day) {
            case MONDAY, FRIDAY, SUNDAY:
                numLetters = 6;
                break;
            case TUESDAY:
                numLetters = 7;
                break;
            case THURSDAY, SATURDAY:
                numLetters = 8;
                break;
            case WEDNESDAY:
                numLetters = 9;
                break;
            default:
                throw new IllegalStateException("Wat: " + day);
        }
        System.out.println(numLetters);
    }

    private enum Week {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,  
        THURSDAY, FRIDAY, SATURDAY
    }
}

続いてSwitch Expressionsを使用した書き方。

SwitchExpressions2
public class SwitchExpressions2 {
    public static void main(String... args) {
        for (Week day : Week.values()) {
            newSwitch2(day);
        }
    }

    // 新しいswitch文
    private static void newSwitch2(Week day) {
        System.out.print("new:");
        int numLetters = switch (day) {
            case MONDAY, FRIDAY, SUNDAY -> 6;
            case TUESDAY                -> 7;
            case THURSDAY, SATURDAY     -> 8;
            case WEDNESDAY              -> 9;
        };
        System.out.println(numLetters);
    }

    private enum Week {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,  
        THURSDAY, FRIDAY, SATURDAY
    }
}

これの効果は一目瞭然ですね。素晴らしい!

JEP 368:Text Blocks (Second Preview)

改行などを含んだ文字列を定義できるようになりました。
文字列を定義する場合の"ではなく"""で囲みます。
開始の"""のあとには文字列を続けることができません。

TextBlocks
public class TextBlocks {
    @SuppressWarnings("preview")
    public static void main(String... args) {
        // これまでは改行をエスケープする必要があった。
        String str1 = "I have a pen.\n"
                + "I don't have a pen.";
        System.out.println(str1);

        // エスケープしなくても改行してくれる。
        String str2 = """
                I have a pen.
                I don't have a pen.
                """;
        System.out.println(str2);

        // 改行したくない場合は「\」を付ける。
        String str3 = """
                I have a pen.\
                I don't have a pen.\
                """;
        System.out.println(str3);

        // 文字列に変数を埋め込む場合
        String str4 = """
                Hello %s.
                """.formatted("taumax");
        System.out.println(str4);
    }
}
実行結果
I have a pen.
I don't have a pen.

I have a pen.
I don't have a pen.


I have a pen.I don't have a pen.

Hello taumax.

以上。

参考

Oracle、「Java 14」を発表 ~Recordクラスがプレビュー導入、switch式が正式機能に
Java 14がリリース

5
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5