Java9とは?開発者に嬉しい9つの新機能を徹底解説!

2017年9月にリリースされたJava9は新しい機能が90個くらい追加されているそうです。

「Java9で何が変わったの?」「新機能はどのように使うの?」「どんなときに新機能を使うの?」

といった方に向けて、今回は初心者向けにJava9の新機能をわかりやすく解説します!


・Javaとは?Javaの特長
・Java9の新機能
・Java9の環境構築
・Java9の環境構築方法
・Java9の新機能

今回はJava9の新機能について、使い方をわかりやすく解説します!

なお、Javaの記事については、こちらにまとめています。

目次

Javaとは?Javaの特長

Java9の説明に入る前に、まずはJavaについて簡単におさらいしておきましょう。

Javaは1990年代にSun Microsystemsが開発・発表したオブジェクト指向という考え方を取り入れた言語です。

2010年にOracleが買収し、Oracle製品の1つになりました。

Javaは家電やモバイル機器を始めとして、多くのデバイスに搭載されています。

国内でもスマートフォンなどに搭載されていて、アプリ開発を行うにはJava言語を使って開発することになります。

2017年9月にリリースされたJava9では多くの新機能が追加されているので、その新機能について解説していきます。

これまでのJavaについては、こちらのサイトでも詳しく解説していますので、ぜひ参考にしてください。

Java9の新機能一覧

Java9のリリース

Java9は2017年9月22日に正式リリースされました。

元々のリリース予定は2016年の6月でしたが、今回追加された「Project Jigsaw」でのモジュール化の開発が難航し、今回のリリースとなっています。

また、Oracle社の発表によると今後のJavaのアップデートは6ヶ月ごとに行う提案がされています。

これまでは数年ごとに大きな機能追加を行ってきましたが、この場合だと数年ごとにしか進化しないというデメリットがあるために、6ヶ月ごとの定期的アップデートを今後は行う予定のようです。

新機能一覧

それではJava9で追加された新機能について解説していきます。

新機能といっても全部で90個くらいあるようですが、ここではよく使われると思われる代表的な9つの新機能について簡単に解説します。

9つの新機能について簡単にまとめました。

項目説明
1JShellコンパイルなしのスクリプトで実行することが可能に
2Project Jigsawモジュール化システム
Javaライブラリの複雑な依存関係、クラスパス設定が解消
3不変コレクションの生成ofメソッドで初期値付き不変コレクションの記述が簡潔に
4匿名クラスでのダイヤモンド演算子匿名クラスの総称型を省略して記述可能に
5Interface内のprivateメソッドInterface内でprivateメソッドを定義可能に
(Java8でdefaultメソッドとstaticメソッドは定義可能)
6try-with-resources文の改良try節内でのクラス宣言が不要に
7Stream APIでのメソッドの追加takeWhile、dropWhile、ofNullableの追加
8Optionalクラスでのメソッドの追加ifPresentOrElse、or、streamの追加
9Deprecatedアノテーションの強化forRemoval(削除されるか?)、since(いつから?)の追加

これらの他にも、JavaScriptエンジン「Nashorn」用APIの強化、Javadocの検索機能の追加などがあります。

それでは表にまとめた9つの新機能について解説していきます!

Java9の環境構築

Java9の新機能を確認する前にJava9での開発環境を構築しなければなりません。

ダウンロードとインストール

Java9はこちらからダウンロードできます。

http://www.oracle.com/technetwork/java/javase/downloads/jdk9-downloads-3848520.html

OSを選択してダウンロードしましょう!

java9.01

インストールについては、Java8以前と大きく変わりません。

こちらのサイトで詳しく解説していますので、参考にしてください。

アップデート

Java9にアップデートするためには現在パソコンにインストールされているJavaのバージョンがJava9かJava8以前か確認する必要があります。

ここでは、使うパソコンのOSはWindows10の場合を代表例として説明します。

Javaのバージョンを確認する方法は以下のとおりです。

Windows 10-プログラムの確認
1.「スタート」をクリックします。
2.「設定」を選択します
3.「システム」を選択します
4.「アプリと機能」を選択します
5.プログラムの一覧からJavaを探し出してバージョンを確認します

Java8check

この画像ではJava8がインストールされています。

Java8以前がインストールされている場合は、Javaをアンインストールする必要があります。

Javaをアンインストールできたら、前章のダウンロードの方法を参考にしてJava9をインストールしてください。

Windows 10-プログラムのアンインストール
1.「スタート」をクリックします。
2.「設定」を選択します
3.「システム」を選択します
4.「アプリと機能」を選択します
5.アンインストールするプログラムを選択し、「アンインストール」ボタンをクリックします。
6.プロンプトに従って、アンインストールを完了します

公式参考サイト
https://java.com/ja/download/faq/remove_olderversions.xml

32bit版がない?

Java9のダウンロードサイトには64bit版のみが並んでいて、32bit版は探しても見つかりません。

32bit版のOSには対応していませんので、注意しましょう!

公式サイトにも以下のコメントが掲載されています。

Dropped Windows 32–bit Client VM
https://docs.oracle.com/javase/9/migrate/toc.htm#JSMIG-GUID-59701F80-5BB1-416D-835D-C39A9112FC1E

Eclipseでの注意点

こちらのサイトで解説しているPleiadesでJava9の開発環境も自動構築することができます。

最新の「Pleiades All in One」を選択するとJava9に対応しています。

Pleiadesの環境が構築できたらJavaのプロジェクトを新規作成するときに「JavaSE-9」を選択してください。

これでJava9を使うことができます。

java903

なお、Eclipseで開発環境を構築する場合はNoClassDefFoundErrorというエラーが発生する場合があります。

Eclipse4.7.1a以降をインストールするようにしましょう。

詳細はこちらのサイトに記載されています。

https://wiki.eclipse.org/Configure_Eclipse_for_Java_9

JShellでスクリプト

Java9の大きな変更点の1つにJShellを使って、スクリプトでJavaを記述、動作確認できるようになりました。

JShellはJavaのREPLツールです。

REPLとは「Read-Eval-Print Loop」の略で、読んで字のごとく「読んで評価して出力を繰り返す」ということになります。

簡単に言うと、JShellを使うとコンパイルなしで対話型で動作確認しながら記述することができます。

それでは、JShellを使って”Hello Java9!”を出力表示してみましょう。

JShellはコマンドラインで「jshell」と入力し、実行すると使えるようになります。

java902

「jshell>」の後にJavaのコードを記述します。

最後に「;」(セミコロン)を記述する必要はありません

タブキーを押すと入力候補も表示されますので、入力するのも簡単です。

ちなみに、Rubyなどのスクリプト言語とコンパイル言語との違いについてはこちらで詳しく解説しています。

ぜひ参考にしてください。

Jigsawでのモジュール化

Java9の大きな変更点の1つにモジュールシステムというものが導入されました。

モジュールとはJavaのパッケージをまとめたもので、他のモジュールをどのように使うか、また他のモジュールからどのように使われるかを制御します。

module-info.javaというソースファイルでモジュール間のアクセスを制御します。

使い方については下記のクイックスタートで紹介されていますので参考にしてください。

http://openjdk.java.net/projects/jigsaw/quick-start

不変コレクションの生成

ListやMapなどのコレクションで要素を初期化して値を変更されたくない場合があります。

Java8までは以下のサンプルコードのように数行に渡って記述する必要があり、とても面倒でした。

Java8までの記述方法:

import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list = Collections.unmodifiableList(list);
        
        System.out.println(list);
    }

}

実行結果:

[a, b, c, d]

これがJava9ではofメソッドを使うことで、簡潔に記述することができるようになりました。

Java9での記述方法:

import java.util.List;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = List.of("a", "b", "c", "d");
        
        System.out.println(list);
    }

}

実行結果:

[a, b, c, d]

ただし、要素の値を変更されたくない場合に使うものですので、以下のように変更しようとするとエラーが発生します。

注意しましょう!

import java.util.List;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = List.of("a", "b", "c", "d");
        
        list.add("e");
        
        System.out.println(list);
    }

}

実行結果:

Exception in thread "main" java.lang.UnsupportedOperationException
        at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:71)
        at java.base/java.util.ImmutableCollections$AbstractImmutableList.add(ImmutableCollections.java:77)
        at Main.main(Main.java:8)

ListやMapの使い方については、こちらのサイトで詳しく解説していますので、ぜひ参考にしてください。

匿名クラスでのダイヤモンド演算子

Java7からダイヤモンド演算子を使って、以下の記述のように右辺で型の指定を省略することができます。

 List<String> list = new ArrayList<>();

Java9ではこれが強化されて、匿名クラスでも使えるようになりました。

ジェネリクス(総称型)については、こちらのサイトで詳しく解説していますので、ぜひ参考にしてください。

匿名クラスについては、こちらのサイトでも詳しく解説していますので、ぜひ参考にしてください。

Interface内のprivateメソッド

Java8からInterface内でdefautメソッドとstaticメソッドが定義できるようにりました。

こちらのサイトで詳しく解説していますので、参考にしてください。

Java9ではさらにprivateメソッドが定義できるようになりました。

defaultメソッドやstaticメソッドの処理内でprivateメソッドを使うことができます。

Interfaceの使い方については、こちらのサイトで詳しく解説していますので、ぜひ参考にしてください。

try-with-resources文の改良

ファイルやデータベースにアクセスするとリソースを解放するためにclose処理を記述する必要がありました。

これを忘れるとメモリリークの原因になったりします。

Java7よりtry-with-resources文が追加され、リソースが確実に閉じられるようになりました。

finallyブロックでcloseメソッドを呼び出さなくても自動でcloseしてくれます。

ただし、以下の記述のようにtry節内でクラスを宣言する必要がありました。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {
        FileReader fr = new FileReader("test.txt");

        try (BufferedReader br = new BufferedReader(fr);) {
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

これがJava9よりtry節内で宣言する必要がなくなりました

以下のように記述できます。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {
        FileReader fr = new FileReader("test.txt");
        BufferedReader br = new BufferedReader(fr);

        try (br) {
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Stream APIでのメソッドの追加

Java8でStream APIが追加され、簡潔に記述できるようになりました。

Stream APIについては、こちらのサイトで詳しく解説していますので、参考にしてください。

Java9ではこのStream APIにさらにメソッドが追加されています。

それぞれのメソッドの使い方についてみていきましょう。

takeWhile

takeWhileメソッドは、条件を満たしている間だけ処理が行われます。

一度条件を満たさなくなると、その後の処理は実行されません。

break文でforループを抜ける記述を簡潔にすることができます。

サンプルコードで確認しましょう。

import java.util.Arrays;
import java.util.List;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = Arrays.asList("s", "a", "m", "u", "r", "a", "i");
        String str = "m";
         
        list.stream().takeWhile(x -> x!= str).forEach(System.out::println);
    }
 
}

実行結果:

s
a

break文でループを抜ける方法については、こちらのサイトで詳しく解説していますので、ぜひ参考にしてください。

dropWhile

dropWhileメソッドは、条件を満たしている間は処理が行われません。

一度条件を満たさなくなると、その後の処理を実行します。

サンプルコードで確認しましょう。

import java.util.Arrays;
import java.util.List;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = Arrays.asList("s", "a", "m", "u", "r", "a", "i");
        String str = "m";
         
        list.stream().dropWhile(x -> x!= str).forEach(System.out::println);
    }
 
}

実行結果:

m
u
r
a
i

ofNullable

ofNullableメソッドは引数に指定する値がnullでない場合はStreamを返します

nullの場合は空のStreamを返します。

nullチェックが必要なくなります

サンプルコードで解説しましょう。

java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

public class Main {
 
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Tokyo", "Oosaka", "Nagoya");
        Map<String, String> map = new HashMap<>() {
            {
                put("Tokyo", "東京");
                put("Osaka", "大阪");
                put("Nagoya", "名古屋");
            }
        };
         
        list.stream().flatMap(x -> Stream.ofNullable(map.get(x))).forEach(System.out::println);
    }
 
}

実行結果:

東京
名古屋

このサンプルコードでは、List型のオブジェクトlistの要素をKeyの値に指定し、Map型のオブジェクトmapのValueを返すように記述しています。

listの要素”Oosaka”はmapのKeyには含まれていないので、Keyに”Oosaka”を指定するとnullを返します。

ofNullableメソッドの引数がnullですので、その場合はエラーも発生せず、出力表示もされていません。

このようにnullチェックが必要なく、簡潔に記述することができます。

Optionalクラスでのメソッドの追加

Java8でOptionalクラスが追加されました。

値のない状態を「null」と言いますが、開発中はnullが原因で意図しないエラーが起こることがよくあります。

そのためif文などを使ってnullチェックの処理を書く必要がありましたが、Optionalクラスを使うと簡潔に書くことができます。

Java9ではこのOptionalクラスにさらにメソッドが追加されました。

Optionalクラスの使い方についてはこちらのサイトで詳しく解説していますので、参考にしてください。

新たに追加されたメソッドの使い方についてみていきましょう。

ifPresentOrElse

Java8で追加されたifPresentメソッドを使うと、nullでない場合のみ引数で指定した処理を行うことができました。

ifPresentOrElseメソッドではnullの場合も処理を行うことができます。

nullでない場合の処理を第1引数に指定します。

nullの場合の処理を第2引数に指定します。

サンプルコードで確認しましょう。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        value.ifPresentOrElse(
            System.out::println, 
            () -> System.out.println("nullです"));
    }
 
}

実行結果:

nullです

or

orメソッドはnullの場合のみ処理を実行します。

orメソッドはOptional型のオブジェクトを返します。

サンプルコードで確認しましょう。

import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        String str = null;
        Optional<String> value = Optional.ofNullable(str);
        System.out.println(value.or(() -> Optional.of("nullです")).get());
    }
 
}

実行結果:

nullです

stream


stream
メソッドを使うと、nullチェックをせずにOptional型のオブジェクトからnullでないものだけを取り出すことができます。

サンプルコードで確認しましょう。

import java.util.List;
import java.util.Optional;
 
public class Main {
 
    public static void main(String[] args) {
        List<String> list1 = List.of("Tokyo", "Osaka");
        List<String> list2 = null;
        
        Optional<List<String>> value1 = Optional.ofNullable(list1);
        Optional<List<String>> value2 = Optional.ofNullable(list2);
        
        value1.stream().flatMap(x -> x.stream()).forEach(System.out::println);
        value2.stream().flatMap(x -> x.stream()).forEach(System.out::println);
    }
    
}

実行結果:

Tokyo
Osaka

List型のオブジェクトlist1はnullではないので、streamメソッドで要素を取得できています。

一方list2の場合はnullであるにもかかわらず、エラーは発生ぜずに処理を実行できています。

Deprecatedアノテーションの強化

Java9ではDeprecatedアノテーションでforRemoval(削除されるか?)、since(いつから?)を指定できるようになりました。

ちなみにDeprecatedアノテーションは、Javaのバージョンが新しくなって以前の記述では非推奨となるけれども、以前の記述のまま残しておきたい場合に使います。

サンプルコードで確認しましょう。

class ClassSample{
    private int num = 0;
    public ClassSample(int num){
        this.num = num;
    }
    @Deprecated(
        forRemoval = false, // 将来削除されるか?
        since = "0.9.1") // いつから非推奨に?
    public int get_num(){
        return num;
    }
    public int getNum(){
        return num;
    }
}
 
public class Main {
 
    public static void main(String[] args) {
 
        ClassSample cs = new ClassSample(1);
        System.out.println("numは " + cs.get_num() + "です");
        System.out.println("numは " + cs.getNum() + "です");
 
    }
 
}

実行結果:

numは 1です
numは 1です

このサンプルコードでは、ClassSampleクラスのget_numメソッドをgetNumメソッドにメソッド名を変更しています。

旧のget_numメソッドに@Deprecatedアノテーションを付けることで、非推奨の警告が出ますが旧のメソッドを削除することなく使用することも出来ています。

forRemoval将来削除されるかどうか指定することができます。

また、sinceいつから非推奨になったかバージョンを指定することができます。

Deprecatedをはじめ、アノテーションの使い方については、こちらのサイトで詳しく解説しています。

ぜひ参考にしてください。

まとめ

今回はJava9の主な新機能について解説してきましたが、いかがでしたか?

JShellJigsawなどの大きな変更があるため細かい部分まで解説しきれなかったのは残念ですが、これらの機能を使いより楽をして品質の高いコードをかけるといいですね!

この記事を書いた人

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
info@sss-lab.com

目次