基本的に、「コードを書く」という視点で新機能を試します。 使用しているのは OpenJDK10 です。
主な新機能一覧
Java9 の新機能を試してみる
JShell
$ jshell | JShellへようこそ -- バージョン10 | 概要については、次を入力してください: /help intro jshell> "string" $1 ==> "string"
便利!
特徴
- セミコロン不要
- 事前コンパイル不要(実行時に自動でコンパイルされる)
- メインクラス・メインメソッド不要
- 一部クラスがインポート済み(java.util 等の使用頻度が高いもの)
- 戻り値が表示される(わざわざ
System.out.println
とか書かなくていい) - 外部ファイルの実行もできる(下記参照)
- タブ補完ができる
// hello-world.java String h = "Hello" String w = "World" System.out.println(h + " " + w)
jshell> /open hello-world.java
Hello World
外部ファイル実行の例です。
セミコロンは不要ですが、戻り値の表示はされないようです。
return
を書いてもダメみたいです。
使いどころ
- ちょっとした動作確認
- Java 以外使用できない Linux などにおいて、シェルスクリプトではやりづらい・書きたくないときに、スクリプト言語として使用
- Java 入門に
不変コレクションのファクトリメソッド
Java8 では……
// List の生成 Arrays.asList("a", "b"); // Map の生成(可変) new HashMap<String, String>() {{ put("key1", "value1"); put("key2", "value2"); }};
Java9 からは……
List.of("a", "b"); Map.of( "key1", "value1", "key2", "value2" );
Map#of
に関しては、タプルがあればもうちょっと良くなったかもしれませんね……
とはいえ、これまで面倒だった Map の初期化も、これでかなり楽になりそうです。
List については、Arrays#asList
がありますが、なにか違いはあるのでしょうか……?
調べてみたいと思います。
匿名クラスでのダイヤモンド演算子
↑の「不変コレクションのファクトリメソッド」の Java8 版で書いたような、匿名クラスを使用するときの型引数を、ダイヤモンド演算子で書けるようになりました。
new HashMap<>() {{ put("key1", "value1"); put("key2", "value2"); }}; // => HashMap<String, String>
Map#of
が追加されたのであまり使い所はなさそうですが、
強いて言えば、ミュータブルな Map の生成にはまだ使うかも……?
インターフェース内の Private メソッド
public interface A { default void defaultMethod() { privateMethod(); } private void privateMethod() { System.out.println("privateMethod!"); } }
たまーーーにほしかったやつ。 デフォルトメソッドやスタティックメソッドと併用して、処理を見やすくするときに使う感じです。
static
もいけます。
モジュールシステム(Project Jigsaw)
散々取り上げられているので、いまさらここには書きません。
べっ、別に、試すのが面倒だからってわけじゃないんだからねっ///
もし後々試したらリンクを張ります。
try-with-resource の改善
private method(ResultSet rs) { try (rs) { while (rs.next()) { System.out.println(rs.getString("name")); } } // rs is closed }
try-with-resource で、かっこのなかで変数の定義をしなくて良くなりました。 処理順の関係で try-with-resource できなかったコードも、これからはできるようになるかもしれません。
ただ、例のようにメソッドに closable を渡すのはアンチパターンかな、とは思います。
Stream#takeWhile
・Stream#dropWhile
List<Integer> list = List.of(1, 2, 3, 4, 5, 6); list.stream().takeWhile((x) -> x < 4).forEach(System.out::print); // => 123 list.stream().dropWhile((x) -> x < 4).forEach(System.out::print); // => 456
地味にほしかったやつ。 Stream を使っていて、途中まで処理したい or 途中から処理したいということがあった人もいるはず。 それが簡単に書けるようになりました。
条件を満たしている間、takeWhile
は処理、dropWhile
はスキップします。
Java10 の新機能を試してみる
var
var str = "string"; var num = 3; var list = List.of("a", 1);
神。
Java10 は以上でーす。
さすがに雑すぎるので追記します。
変数の型の代わりにvar
を書くことによって、ローカル変数の型推論がされ、適切な型になります。
最初のうちは型名を書くのに慣れているのであまり使うことはないかもしれませんが、new
で代入する変数などはこれでいいかもしれませんね。
私? もちろん、ローカルはほぼ全部var
で置き換えます。
まとめ
Java9 は、大きな変更としてはモジュールシステムがありますが、それ以外にも細かい改善が多いですね。 「これがなきゃやってられない!」ではなく、「これがあるとかなり便利!」という方向だと感じました。
Java10 は内部の改善が主なので上に書いてある内容は少ないですが、var
の導入という神アップデートがありました。
これは今後のJavaの書き方を考えさせられる内容です。
個人的には、「これがなきゃやってられない」です。
モジュールシステムは、大きめのJavaプロジェクトを管理する際に、 今後必須になってくるくらい影響があると思われます。 そういうプロジェクトにがっつり関わったことはないんですけどね。悲しいことに。
これからの Java のリリースサイクルは半年とだいぶ短くなりますが、 2018/9 リリース予定の Java11 が LTS のようなので、そこまで徐々にアップデートしていきたいですね。