Java11でのAPI変更を雑に列挙

先月末でJDK11はRampdownフェーズに入って、機能凍結されました。
なので、今後はAPIの追加・削除・変更はほとんどないと思われます。
おそらく、機能的には現在でているea20とほとんど同じものがJava11としてリリースされることになると思います。
JDK 11 Early-Access Builds


大きな機能変更としては、ここでJEPとしてまとまっています。
JDK 11」 http://openjdk.java.net/projects/jdk/11/
Raw String Literalが間に合わなかったのはとても残念です。JDK11トレインに乗り遅れるからがんばるぞ!みたいな投稿があって仕様をまとめてからML上は音沙汰なしですが、Rampdownフェーズが始まってから機能追加するLate Enhancement Request Processというのがあるようなので、ここに賭けましょう。
JEP 3: JDK Release Process


Switch ExpressionはRelease 12とターゲットが明記されていますが、Raw String Literalsは まだターゲットが明記されておらず、11に入れることを諦めたわけではないと、一縷の望みが。
JEP 325: Switch Expressions
JEP 326: Raw String Literals


ともあれ、JDK11ではJEPにあげられている以外の変更も多く入っています。そこで、いま個人的に把握している範囲でのAPI変更を列挙しておきます。

String

repeat(int)

文字列を指定した回数繰り返します。

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

空白だけかどうかを判定するメソッドが追加されました。全角スペースも空白として判定されます。

jshell> var halfSpace = "\u0020"
halfSpace ==> " "

jshell> halfSpace.isBlank()
$11 ==> true

jshell> var fullSpace = "\u3000"
fullSpace ==> " "

jshell> fullSpace.isBlank()
$13 ==> true
strip() / stripLeading() / stripTrailing()

trim() / trimLeft() / trimRight() とほぼ同じ役割なのですが、全角スペースなども空白とみなされるところが違います。

jshell> var aaa = fullSpace + "aaa" + fullSpace
aaa ==> " aaa "

jshell> aaa.strip()
$14 ==> "aaa"

jshell> aaa.trim()
$15 ==> " aaa "

CharSequence

compare(CharSequence, CharSequence)

辞書順に文字列を比較します
動作的にはStringのcompareToがa.compareTo(b)と書けていたのがCharSequenceに対応してstaticメソッドになった感じですね。どちらかがnullならぬるぽです。

Character

toString(int)

いままで微妙に不便だったのがちょっと便利になりました。
JDK10.0.1

jshell> Character.toString(65)
|  エラー:
|  不適合な型: 精度が失われる可能性があるintからcharへの変換
|  Character.toString(65)
|                     ^^


JDK11ea14

jshell> Character.toString(65)
$9 ==> "A"

Path

of(String, String...)

いままでPaths.get()を使っていたところが、ほかの作法と同様にof()で得れるようになりました。

Files

writeString(Path, CharSequence)

1メソッドで文字列保存できるようになりました。

jshell> Files.writeString(Path.of("test.txt"), "Hello!!!")
$3 ==> test.txt
readString(Path)

1メソッドで文字列読み込みできるようになりました。

jshell> Files.readString(Path.of("test.txt"))
$4 ==> "Hello!!!"

Predicate

not(Predicate)

条件を反転する必要があるためにメソッド参照が使えなかったところで、メソッド参照が使えるようになります。

jshell> Stream.of("aa", "", "bb").filter(Predicate.not(String::isEmpty)).toArray()
$23 ==> Object[2] { "aa", "bb" }

Collection

toArray(IntFunction)

いままで型をちゃんとあわせた配列をListなどから作るのにlist.toArray(new String[list.size())])みたいなかっこわるい記述が必要だったのが、ちょっとかっこよく書けるようになりました。

jshell> List.of("aa","bb").toArray(String[]::new)
$1 ==> String[2] { "aa", "bb" }

Optional

isEmpty()

いままでisPresent()はありましたが、isEmpty()も追加されました。

jshell> Optional.ofNullable(null).isEmpty()
$5 ==> true

Pattern

asMatchPredicate()

asPredicateはfindするPredicateだったのですが、matchするPredicateが用意されました。

jshell> var pred = Pattern.compile("aaa").asPredicate()
pred ==> java.util.regex.Pattern$$Lambda$25/0x00000008000b5040@2f686d1f

jshell> pred.test("aaab")
$7 ==> true

jshell> var matPred = Pattern.compile("aaa").asMatchPredicate()
matP ==> java.util.regex.Pattern$$Lambda$24/0x00000008000b6440@402a079c

jshell> matPred.test("aaab")
$9 ==> false

Thread

destroy() / stop(Throwable)

削除されました。stop()は残ってます。

ArrayIndexOutOfBoundsException

メッセージが人類に優しくなりました。
JDK10.0.1

jshell> new int[]{}[0]
|  java.lang.ArrayIndexOutOfBoundsException thrown: 0
|        at (#8:1)


JDK11-ea14

jshell> new int[]{}[0]
|  Exception java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
|        at (#4:1)

IndexOutOfBoundsException

むやみにハイフンが入ってたのが取り除かれました。
JDK10.0.1

jshell> List.of().get(0)
|  java.lang.IndexOutOfBoundsException thrown: Index 0 out-of-bounds for length 0
|        at Preconditions.outOfBounds (Preconditions.java:64)
|        at Preconditions.outOfBoundsCheckIndex (Preconditions.java:70)
|        at Preconditions.checkIndex (Preconditions.java:248)
|        at Objects.checkIndex (Objects.java:372)
|        at ImmutableCollections$List0.get (ImmutableCollections.java:106)
|        at (#6:1)


JDK11-ea14

jshell> List.of().get(0)
|  Exception java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
|        at ImmutableCollections$ListN.get (ImmutableCollections.java:411)
|        at (#3:1)


実はList.of()がList0とかList1とか要素数にあわせた専用クラスのインスタンスを返してたのですが、それもListNに統一されたことがわかります。

System

arraycopy

エラーメッセージが人類に優しくなりました。
JDK10

jshell> System.arraycopy(new int[0],0,new double[0],0,0)
|  java.lang.ArrayStoreException thrown


JDK11ea19

jshell> System.arraycopy(new int[0], 0, new double[0], 0, 0)
|  Exception java.lang.ArrayStoreException: arraycopy: type mismatch: can not copy int[] into double[]
setProperty(String, String)

いままでjava.homeとかをいじるとエラいことなってたと思うのですが、システムに影響がなくなりました。たぶん。

Swing

ea20からフォント描画でユニコードのバリエーションセレクタが反映されるらしい。未確認。

Base64

ea20からエンコードにAVX512を使うようになったので速くなった、らしい。
Windowsでは確認できませんでした。Linuxだけかも。

Boolean

parseBoolean

無駄なnullチェックを省いてちょっと速くなった、らしい。
JDK10

    public static boolean parseBoolean(String s) {
        return ((s != null) && s.equalsIgnoreCase("true"));
    }


JDK11

    public static boolean parseBoolean(String s) {
        return "true".equalsIgnoreCase(s);
    }

差については未確認

List

copyOf

Java10で導入されたcopyOfですが、subListをコピーするときの挙動がダメだったらしい。シリアライズができない。
ここまでは共通。

jshell> var list1 = List.of("a","b","c")
list1 ==> [a, b, c]

jshell> var list2=list1.subList(1,2)
list2 ==> [b]

jshell> var list3=List.copyOf(list2)
list3 ==> [b]


JDK11ea19

jshell> list2==list3
$13 ==> true

jshell> new ObjectOutputStream(OutputStream.nullOutputStream()).writeObject(list3)
|  Exception java.io.NotSerializableException: java.util.ImmutableCollections$SubList
|        at ObjectOutputStream.writeObject0 (ObjectOutputStream.java:1185)
|        at ObjectOutputStream.writeObject (ObjectOutputStream.java:349)
|        at (#14:1)


JDK11ea20

jshell> list2==list3
$26 ==> false

jshell> new ObjectOutputStream(OutputStream.nullOutputStream()).writeObject(list3)

jshell>

TimSort

なんかバグがあって修正されたぽい
https://blog.satotaichi.info/timsort-was-broken/