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";
指針については次のような感じがいいかなと。
-
new
、List.of
など右辺に型があるものはvar
を使う方がいい(Integer
、Long
など以外) -
java.lang
、java.util
などの基本的なクラスにはvar
を使っていい -
Integer
やLong
などラッパークラスは扱い注意なのでvar
を使わないほうがいい - 基本型には
var
を使ってもいい - アプリケーションクラスには
var
を使わないほうがいい
ラッパークラスの変数を使う場合はnullを扱うということなので、型を明示しておいたほうがいいと思います。nullを使わないなら基本型を。
項目1に当てはめると次のような書き方はOKになります。
var count = Long.valueOf("123");
けれども、Integer
やLong
のメソッドに関しては基本型を返すものとラッパー型を返すものが混在しているので、型を明示しておいたほうが安全です。
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
ZGC
CMS is deprecated
Ahead of time compilation
機能
JShell
Launch Single-File Source-Code Programs
ソース1つのJavaコードをjavacでコンパイルすることなくjavaコマンドで実行できるようになりました。