先月末で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とかをいじるとエラいことなってたと思うのですが、システムに影響がなくなりました。たぶん。
新元号対応
とりあえずNEWERAとして入ってます。
Javaの新元号対応を試す。そして実用には問題がある - きしだのはてな
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/