Java 13が2019/9/17にリリースされています。
Java SE 13 Platform JSR 388
ダウンロード
OpenJDKサイトからダウンロードできていました。
https://jdk.java.net/13/
現在はアーカイブサイトからダウンロードできます。
https://jdk.java.net/archive/
LTSではないので、検証目的以外には今からダウンロードする必要もないと思いますけど。
MacやLinuxでのインストールにはSDKMAN!をお勧めします
Oracle OpenJDK以外に無償で商用利用できるディストリビューションとしては、次のようなものがあります。
LTSではないのでAmazon Correttoではリリースされないようです。
Oracle JDKは開発用途には利用できますが、商用利用にはJava SE Subscriptionを購入する必要があります。
JEP
変更はJEPとしてまとまっています。
https://openjdk.java.net/projects/jdk/13/
今回は5つほどJEPが入っています。
JEP 350: Dynamic CDS Archives
JEP 351: ZGC: Uncommit Unused Memory (Experimental)
JEP 353: Reimplement the Legacy Socket API
JEP 354: Switch Expressions (Second Preview)
JEP 355: Text Blocks (Preview)
JEP 355: Text Blocks (Preview)
複数行の文字列リテラルがプレビューとして導入されました。
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
スペースのエスケープなどが追加されて、Java 15で標準になります。
詳しい仕様はJava 14の説明のほうをみてください。
Java 14新機能まとめ - Qiita
JEP 354: Switch Expressions (Second Preview)
Switch文を式にします。
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
Java 12と比べると、switch式で値を返す構文がbreak
からyield
になりました。
Java 14で標準化されています。
詳しい仕様はJava 14の説明のほうをみてください。
Java 14新機能まとめ - Qiita
JEP 350: Dynamic CDS Archives
-XX:ArchiveClassesAtExit
をつけることで実行時にCDSアーカイブを作成します。
使い方はこちらが参考になると思います。
Java 13のDynamic CDSで想像以上に起動速度が速くなった - きしだのHatena
試した感じでは、実行時ではなくふつうにCDSアーカイブ作った方が起動が速かった。
Dynamic CDSよりJava10からある自力ダンプの方が起動が速い - きしだのHatena
JEP 351: ZGC: Uncommit Unused Memory (Experimental)
ZGCでつかってないメモリが解放されるようになります。
JEP 353: Reimplement the Legacy Socket API
TCPソケットAPIを実装しなおして、Project Loomでの非同期処理に対応しています。
API
APIもいくつか変更されています。
String
TextBlocks関連のAPIが追加されています。
ただし、Java 13の時点では@Deprecated
指定されているだけでいつでも使えますが、Java 14では--enable-preview
をつけたときにだけ使えるようになっています。
formatted
String.format
をインスタンスメソッドとして使えるようにする。
たとえば
callQuery(String.format("select * from table where id=%d", id));
と書いていたものが
callQuery("select * from table where id=%d".formatted(id));
のように書けて便利。
https://bugs.openjdk.java.net/browse/JDK-8203444
translateEscapes
\n
などをエスケープ文字として扱う。
コードを見るとエスケープが入り混じってまぎらわしいですが、文字列中の\n
が改行に変換されています。
jshell> var s = "test\\ntest\\n"
s ==> "test\\ntest\\n"
jshell> System.out.println(s)
test\ntest\n
jshell> s.translateEscapes()
$18 ==> "test\ntest\n"
jshell> System.out.println(s.translateEscapes())
test
test
stripIndent
インデントを取り除きます。
Map.ofで要素数1のMapに対するget(null)がぬるぽ
JDK9でMap.of
が追加されています。
JDK9、JDK10では要素数0のときはMap0
、要素数1のときMap1
、要素数2以上のときMapN
のインスタンスが返っていて、Map.of().get(null)
はnull
を返していました。
C:\Users\naoki>java\jdk\jdk-10.0.1\bin\jshell
| JShellへようこそ -- バージョン10.0.1
| 概要については、次を入力してください: /help intro
jshell> Map.of().get(null)
$1 ==> null
jshell> Map.of(1,2).get(null)
$2 ==> null
jshell> Map.of(1,2,3,4).get(null)
| java.lang.NullPointerException thrown
| at ImmutableCollections$MapN.probe (ImmutableCollections.java:779)
| at ImmutableCollections$MapN.get (ImmutableCollections.java:721)
| at (#3:1)
JDK11で要素数0の場合もMapN
を使うようになってMap.of().get(null)
がぬるぽになってます。
C:\Users\naoki>java\jdk\jdk-11.0.1\bin\jshell
| JShellへようこそ -- バージョン11.0.1
| 概要については、次を入力してください: /help intro
jshell> Map.of().get(null)
| 例外java.lang.NullPointerException
| at Objects.requireNonNull (Objects.java:221)
| at ImmutableCollections$MapN.get (ImmutableCollections.java:843)
| at (#1:1)
jshell> Map.of(1,2).get(null)
$2 ==> null
jshell> Map.of(1,2,3,4).get(null)
| 例外java.lang.NullPointerException
| at ImmutableCollections$MapN.probe (ImmutableCollections.java:926)
| at ImmutableCollections$MapN.get (ImmutableCollections.java:846)
| at (#3:1)
Map.of(1,2).get(null)
の場合はJDK9からJDK12までnull
を返していました。
JDK13からはMap.of(1,2).get(null)
も ぬるぽになります。
以前のバージョンもJDK12.0.2や、JDK11.0.4で修正されています。
ここで、nullチェックのためにrequireNonNullじゃなくてequals呼び出しを使ってるところも面白いですね。
Numberのデフォルトコンストラクタ
Number
クラスにデフォルトコンストラクタが追加されました。
といっても実装はこんな感じです。
public Number() {super();}
これ、定義しなくても暗黙で定義されるので不要ですよね。
なんかlintをだまらせるために追加したっぽい
JapaneseEraへの令和の追加
2019/5/1に新しい元号「令和」が始まりました。
Java 8のアップデートやJava 11、Java 12でもフォーマットやパースでは令和に対応していたのですが、JapaneseEraには正式には定義されていませんでした。
Java 13からJapaneseEra.REIWA
が使えるようになりました。
Java 11では元号は決まっていなかったのでNewEraとして表示されていました。
jshell> java.time.chrono.JapaneseDate.now()
$1 ==> Japanese NewEra 2-07-21
11.0.3では元号が決まっていたのでREIWAという表示になりました。
jshell> java.time.chrono.JapaneseDate.of(2020,5,1)
$1 ==> Japanese Reiwa 2-05-01
これに対するJapaneseEra.NEWERA
やJapaneseEra.REIWA
も定義されてはいたのですが、package privateになっていてコードから使えなかったのですが、Java 13からはpublicになって誰でも使えるようになりました。
ツール
rmicに少し変更が入っています。
rmicで--preview-featureがついたものを通さないようにする
rmicをdeprecatedに。そしてそのうち消す
[JDK-8217412] deprecate rmic for removal - Java Bug System
Java 15で消えています。