LoginSignup
285
249

More than 1 year has passed since last update.

Java8からJava11への変更点

Last updated at Posted at 2018-12-14

Java 8からJava 11

http://openjdk.java.net/projects/jdk9/
http://cr.openjdk.java.net/~iris/se/9/latestSpec/apidiffs/overview-summary.html

https://openjdk.java.net/projects/jdk/10/
http://cr.openjdk.java.net/~iris/se/10/latestSpec/apidiffs/overview-summary.html

https://openjdk.java.net/projects/jdk/11/
http://cr.openjdk.java.net/~iris/se/11/latestSpec/apidiffs/overview-summary.html

言語

まず言語についての変更点です。

var

http://openjdk.java.net/jeps/286
ローカル変数について型推論ができるようになりました。

var a = "Foo";

指針については次のような感じがいいかなと。

  • newList.ofなど右辺に型があるものはvarを使う方がいい(IntegerLongなど以外)
  • java.langjava.utilなどの基本的なクラスにはvarを使っていい
  • IntegerLongなどラッパークラスは扱い注意なのでvarを使わないほうがいい
  • 基本型にはvarを使ってもいい
  • アプリケーションクラスにはvarを使わないほうがいい

ラッパークラスの変数を使う場合はnullを扱うということなので、型を明示しておいたほうがいいと思います。nullを使わないなら基本型を。
項目1に当てはめると次のような書き方はOKになります。

var count = Long.valueOf("123");

けれども、IntegerLongのメソッドに関しては基本型を返すものとラッパー型を返すものが混在しているので、型を明示しておいたほうが安全です。
varで受け取る場合は基本型になっている、というふうにしておいたほうがいいと思います。

private interface methods

interfaceにprivateメソッドが使えるようになりました。

Java8 でstaticメソッドやdefaultメソッドが使えるようになっているので、その共通処理をprivateで書くことができます。

effective final in try-with-resource

実質的にfinalな変数について、try-with-resourceで変数だけを指定することができるようになりました。
いままではtryの外で定義されたClosableな変数についてtry-with-resourceで自動closeしたいときは、別の変数に割り当てるということが必要でした。例えばfinallyで使いたいという場合にtryの外での変数定義が必要でしたが、そういう場合に使えます。

var io = new InputStream();
try (var io2 = io) {
  ...
}

var io = new InputStream();
try (io) {
  ...
}

<> in anonymous

匿名クラスにダイヤモンド演算子での型推論ができるようになりました。

List<String> strs = new ArrayList<>() {{
  this.add("aa");
  this.add("bb");
}};

_が利用不可

変数として_が使えないようになりました。

API

ここからは標準ライブラリの変更点についてクラスごとにまとめます。

Java 11のAPIについてはこちらもどぞ
https://nowokay.hatenablog.com/entry/20180704/1530712754

java.lang

String

Compact String

http://openjdk.java.net/jeps/254
Java9で入っています。
Java8までは文字をcharとしてUTF-16で保持していたので1文字につき2バイトを使っていましたが、アルファベットや数字などASCIIキャラクタだけの文字列は1バイトで保持するようになりました。

Indy String concatenation

いままで、+での文字列の連結はStringBuilderに展開されましたが、InvokeDynamicで実行時に確定するようになります。

"aa"+ a

new StringBuilder("aa").append(a);


Dynamic Invoke

repeat(n)

繰り返せる

jshell> "test".repeat(3)
$1 ==> "testtesttest"

isBlank()

isBlankはUTFのスペース文字

strip() / stripLeading() / stripTrailing()

trim() / trimLeft() / trimRight()のUTF対応版

lines()

改行ごとの文字列のStreamを返す

"test\nprogram\n".lines()
  .map(String::strip)
  .collect(Collectors.joining("\n"))

のようにすると各行の前後のスペースが取り除けるわけです。

java.util

List/Set/Map

of

Immutableなコレクションを返します

var strs = List.of("apple", "banana");
var sets = Set.of("apple", "banana");
var dict = Map.of(
  "apple", "りんご",
  "banana", "バナナ");

copyOf

Immutableなコピーを返す

Map

ofEntries() / entry()

MapにはofだけでなくofEntries()も追加されています。

import static java.util.Map.entry;

var map = Map.ofEntries(
  entry("key1", "value1"),
  entry("key2", "value2"));

Predicate

not

メソッドリファレンスの反転が便利に

lines.stream()
  .filter(not(String::isEmpty))
  .forEach(System.out::println);

Collection

toArray(IntFunction)

Listなどを配列に変換するとき、サイズをあわせた配列をあらかじめ用意する必要がありましたが、strs.toArray(String[]::new)のようにして配列を生成できます

Stream

dropWhile / takeWhile

Java 8では「データにstartがきてからendがくるまで」というようなStream処理はできませんでしたが、Java 9で導入されたdropWhile / takeWhileを使うと実装できるようになります。

jshell> Stream.of("one", "start", "two", "three", "end", "four").
   ...> dropWhile(s -> !s.equals("start")).
   ...> takeWhile(s -> !s.equals("end")).
   ...> forEach(System.out::println)
start
two
three

この場合startまで入っているので、skipする必要がありますね。

jshell> Stream.of("one", "start", "two", "three", "end", "four").
   ...> dropWhile(s -> !s.equals("start")).
   ...> skip(1).
   ...> takeWhile(s -> !s.equals("end")).
   ...> forEach(System.out::println)
two
three

ofNullable

iterate

引数2つのiterateはJava8からありましたが、必ずlimitなどで停止条件をつける必要がありました。

IntStream.iterate(0, i -> i + 3).limit(5)
  .forEach(System.out::println);

takeWhileもなかったので、結構使いどころが難しかったです。
そして、takeWhileを組み合わせてiterateを使えるようになりました。
ということで、for文のように使えます。

IntStream.iterate(0, i -> i < 10, i -> i + 3)
  .forEach(System.out::println);

これ、次のような書き方をすると帰ってこなくなります。なぜかは考えてみてください。

IntStream.iterate(0, i -> i < 10, i -> i++)
  .forEach(System.out::println);

これならいける

IntStream.iterate(0, i -> i < 10, i -> ++i)
  .forEach(System.out::println);

Optional/OptionalInt/OptionalLong/OptionalDouble

orElseThrow()

isEmpty()

stream()

OptionalからStreamへの変換が簡単になりました。
このことで、Stream中でOptionalが帰ってくるときにfilter(Optional::isPresent)をはさむ必要がなくなっています。
たとえばgetByIdがOptionalを返すとして

ids.map(Data::getById)
   .filter(Optional::isPresent)
   .collect(Collectors.toList())

のようにしていたものを

ids.flatMap(id -> getById(id).stream())
   .collect(Collectors.toList())

のような感じでflatMapで書けるようになります。

ifPresentOrElse

or

OptionalがEmptyなら次のOptionalのようなことが書きやすくなりました。

Collectors

toUnmodifiableList / toUnmodifiableSet / toUnmodifiableMap

イミュータブルなコレクションに値を格納するCollectorです

filtering

flatMapping

Enumeration

asIterator

Objects

requireNonNullElse

requireNonNullElseGet

java.io

Path

of

Files

writeString

テキストをファイルに書き込む処理が一行に。

readString

テキストをファイルから読み込む処理が一行に。

Reader

transferTo

Readerで読み取った内容をそのままWriterに書くということが一行に

nullReader

Writer

nullWriter

InputStream

transferTo

InputStreamで読み取った内容をそのままOutputStreamに書くということが一行に

nullInputStream

OutputStream

nullOutputStream

java.net.http

HTTPアクセスが刷新されました。

sun.misc

いろいろ削除されたっぽい

sun.misc.BASE64Encoder / BASE64Decoder

Java9で削除されているので代わりにjava.util.BASE64.Encoder / Decoderを使う

JVM

Log

http://openjdk.java.net/jeps/158
http://openjdk.java.net/jeps/271

G1GC is the default GC

http://openjdk.java.net/jeps/248

ZGC

CMS is deprecated

Ahead of time compilation

機能

JShell

Launch Single-File Source-Code Programs

ソース1つのJavaコードをjavacでコンパイルすることなくjavaコマンドで実行できるようになりました。

Module System

Java EE and CORBA is dropped

285
249
3

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
285
249