きしだのはてな このページをアンテナに追加 RSSフィード

2018-07-08(日) ロケールを指定してJShellを起動

[]ロケールを指定してJShellを起動 21:39 ロケールを指定してJShellを起動を含むブックマーク

  • J-Duser.language=enをつける
C:\Users\naoki>java\jdk-10.0.1\bin\jshell -J-Duser.language=en
|  Welcome to JShell -- Version 10.0.1
|  For an introduction type: /help intro

nonamenoname 2018/07/10 14:24 それは言語であってロケールではないのでは...まあ、言語も込みかな(user.countryも使えばいいのかな)

nowokaynowokay 2018/07/12 03:36 あ、確かに

トラックバック - http://d.hatena.ne.jp/nowokay/20180708

2018-07-07(土) Java 11 API changes

[][]Java11 API Changes 22:59 Java11 API Changesを含むブックマーク

JDK11 features are frozen since it was in the Rampdown phase last month.


Big changes are listed in this page as JEPs.

JDK 11


However there are many changes outside of JPEs in JDK 11, therefore I list up the API changes in JDK 11 as far as I know.


String

lines()

Get a stream divided by line breaks.

jshell> "test\nhoge\n".lines().map(String::toUpperCase).toArray()
$11 ==> Object[2] { "TEST", "HOGE" }

repeat(int)

Repeat string for the specified times.

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

isBlank()

The method appended that determines whether the string contains only spaces or not. Full width space is also treated as a space.

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

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

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

jshell> fullSpace.isBlank()
$13 ==> true

strip() / stripLeading() / stripTrailing()

Almost same as trim() / trimLeft() / trimRight() but it takes full width spaces as a spece.

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

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

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

CharSequence

compare(CharSequence, CharSequence)

Sort by dictionaly order.

It is used by compateTo in CharSequence/StringBuffer/StringBuilder. Therefore the 3 classes implements Comparable.


Character

toString(int)

It was not convenient so far but now it become convenient.

JDK10.0.1

jshell> Character.toString(65)
|  Error:
|  incompatible types: possible lossy conversion from int to char
|  Character.toString(65)
|                     ^^

JDK11ea14

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

Path

of(String, String...)

We had to use Paths.get() so far, now we can use of() as same manner as another classes.


Files

writeString(Path, CharSequence)

We can save a string with 1 method.

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

readString(Path)

We can read a string with 1 method.

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

Reader

nullReader()

We can get a Reader that do nothing.


Writer

nullWriter()

We can get a Writer that do nothing.


Predicate

not(Predicate)

We could not use a method reference where it needs to invert the condition, now we can use a method reference.

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

Collection

toArray(IntFunction)

We had to use a non stylish notation like list.toArray(new String[list.size())]) on creating an typed array from a collection, now we can write in a stylish notation.

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

Optional/OptionalInt/OptionalLong/OptionalDouble

isEmpty()

isPresent() had existed so far, now we have isEmpty().

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

TimeUnit

convert(Duration)

added for java.util.concurrent.TimeUnit


Pattern

asMatchPredicate()

There was asPredicate that do find, now we have asMatchPredicate that do match.

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

jshell> pred.test("aaa")
$6 ==> true

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("aaa")
$9 ==> true

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

ListSelectoinModel

getSelectedIndices()/getSelectedCount() are added.

Swing is changing!


Thread

destroy() / stop(Throwable)

Removed. stop() remains.


Policy

javax.security.auth.Policy is removed.


ArrayIndexOutOfBoundsException

The message become gentle for human.

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

hyphens are removed in the message.

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)

System

arraycopy

The message become gentle for human.

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)

So far changing java.home would make trouble but now it is not affect for the system, maybe...


Support Japanese new era.

It is introduced as NEWERA

Javaの新元号対応を試す。そして実用には問題がある - きしだのはてな


Base64

Since ea20, the encoding become faster by using AVX512, but I can not confirm on Windows.


Boolean

parseBoolean

It become lettle faster to remove redundant null check, they said.

JDK10

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

JDK11

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

I haven't confirmed it yet.


List

copyOf

copyOf that has introduced since Java10, it was wrong copying a subList. It could not be serialized. Now fixed.

Common initialize.

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

There are some bug, but fixed, maybe.

https://blog.satotaichi.info/timsort-was-broken/

トラックバック - http://d.hatena.ne.jp/nowokay/20180707

2018-07-04(水) Java11でのAPI変更を雑に列挙

[]Java11でのAPI変更を雑に列挙 22:59 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とかをいじるとエラいことなってたと思うのですが、システムに影響がなくなりました。たぶん。


元号対応

とりあえずNEWERAとして入ってます。

Javaの新元号対応を試す。そして実用には問題がある - きしだのはてな


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/

2018-06-18(月) Java9から三項演算子でのunboxingの挙動がJava8とは変わっている

[]Java9から三項演算子でのunboxingの挙動がJava8とは変わっている 20:51 Java9から三項演算子でのunboxingの挙動がJava8とは変わっているを含むブックマーク

Java9からJDK11-ea18まで、三項演算子でのunboxingの挙動がJava8とは変わっているようです。


次のようなコードの挙動がJava8でコンパイルしたときとJava9以降でコンパイルしたときとで変わっています。

Double d = false ? 1.0 : new HashMap<String, Double>().get("a");

試しに次のようなコードを実行してみます。

import java.util.HashMap;

public class BoxingBehavior {
    public static void main(String[] args) {
        System.out.println(System.getProperty("java.version"));
        Double d = false ? 1.0 : new HashMap<String, Double>().get("a");
        System.out.println(d);
    }
}

Java8ではdにnullが入ります

1.8.0_151
null

Java9以降ではNullPointerExceptionが発生します。

Exception in thread "main" 9.0.4
java.lang.NullPointerException
	at com.mycompany.BoxingBehavior.main(BoxingBehavior.java:17)

Java9以降のコンパイラでtargetを1.8にしても発生します。また、コンパイラのバグなので、Java9以降でtargetを1.8にしてコンパイルしたバイナリをJava8で動かしても発生します。


これ、Java6のときから何度か発生しているようなのに、また発生したということは、この時点でテストをちゃんと作らなかったのが問題じゃないですかね。

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6977221

https://bugs.openjdk.java.net/browse/JDK-8062801


※追記 こちらの挙動のほうが正しいっぽいので、バグじゃないらしく、Java8までがバグだったぽい

※追記(6/19) Java言語仕様15.25 条件演算子の表15.25-D

Chapter 15. Expressions

2018-06-17(日) Java11ではjavacせずにJavaファイルが実行できるようになる

[]Java11ではjavacせずにJavaファイルが実行できるようになる 21:43 Java11ではjavacせずにJavaファイルが実行できるようになるを含むブックマーク

JDK11 ea18から、javacしないでもJavaファイルを実行できるようになりました。

あと、Windowsバイナリはzipファイルで提供されるようになっています。tarコマンドが提供されたとはいえ、エクスプローラーから解凍できるzipファイルになるのは ありがたい。

JDK 11 Early-Access Builds


JEP330が取り込まれたことにより、ソースファイルがひとつのJavaプログラムは、javac不要でjavaコマンドで実行できるようになります。

JEP 330: Launch Single-File Source-Code Programs


Windowsコマンドプロンプトだと こんな感じ。

C:\Users\naoki\java>more Hello.java
public class Main {
  public static void main(String... args) {
    System.out.println("Hello!!");
  }
}

C:\Users\naoki\java>jdk-11-ea18\bin\java Hello.java
Hello!!

これはインタプリタのように逐次ソースコードを読みながら実行するというわけではなく、内部的には、次のようにメモリに出力してコンパイルが行われ、そのメモリ内容を実行するような処理になっています。

javac -d <memory> Hello.java
java -cp <memory> Main

ここで注目してもらいたいのは、ファイル名とクラス名が一致していないところです。


ただし、すでにクラスパス上にコンパイル済みclassファイルがある場合はエラーになります。

C:\Users\naoki\java>jdk-11-ea18\bin\java Hello.java
error: class found on application class path: Main

拡張子javaを付けない場合でも、--source指定をすれば直接実行ができます。

C:\Users\naoki\java>more hello
public class Main {
  public static void main(String... args) {
    System.out.println("Hello!!");
  }
}

C:\Users\naoki\java>jdk-11-ea18\bin\java --source 11 hello
Hello!!

これを利用すると、ShebangとしてJavaファイルをコマンドのように実行することもできます。Cygwinですが、次のようになりました。

naoki@DESKTOP-P96N9VS ~$ cat hello
#! /cygdrive/c/Users/naoki/java/jdk-11-ea18/bin/java --source 11
public class Main {
  public static void main(String... args) {
    System.out.println("Hello!!");
  }
}

naoki@DESKTOP-P96N9VS ~$ ls hello -l
-rwxr-xr-x 1 naoki naoki 171 6月  17 17:50 hello

naoki@DESKTOP-P96N9VS ~$ ./hello
Hello!!

Javaを少し気軽に実行できるようになりますね。入門には とてもいいと思います。