エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

Java10 JEP286 試し実装

Java10

JDK 10

JEP286

JEP 286: Local-Variable Type Inference

  • 要約の翻訳
    ローカル変数を型推論を使って初期化するための拡張実装案です。

試し実装

実装する前に試した結論から言うと、型を書かなくても良くなっただけで、失くなったわけではない。

環境

確認したバージョン。

$ java -version
java version "10-ea" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10-ea+37)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10-ea+37, mixed mode)

とりあえず使う

var型が追加されたので、使ってみる。

import java.util.*;

class TestJEP286 {
  public static void main(String[] args) {
    var list = new ArrayList<String>();
    list.add("test");
    System.out.println(list.get(0).getClass());
    System.out.print(list);
  }
}

実行結果は下記になるはず。

$ java TestJEP286
class java.lang.String
[test]

listは、特に型を指定してないけど、追加してもエラーは発生しない。
そして、getClassした値は、ちゃんと java.lang.String になっているはず。

意地悪してみる

新しいことをしているやつは、とりあえず痛めつけたい考えがある。
もちろん、対人関係でそんなことはしませんけど。
なんというか、新しいものをいじり倒したい願望が結構強い。

別な型を入れる

さっきの実装を下記に変える。

    var list = new ArrayList<String>();
    list.add(1);
    System.out.println(list.get(0).getClass());
    System.out.print(list);

型指定してないから、数値をぶっ込んでみる。
すると、下記の結果が返る。

$ javac TestJEP286.java
TestJEP286.java:6: エラー: 不適合な型: intをStringに変換できません:
    list.add(1);
             ^
注意:一部のメッセージは簡略化されています。-Xdiags:verboseで再コンパイルして
完全な出力を取得してください
エラー1個

想定通りの反応。
型が違うので、入れることはできない。
指定されてないからといって、なんでも入れられるわけではない。
コンパイルエラーになるので、型が指定されてないからわかんないってことは起きない。
そもそも、分からないってことは、ソースを理解してないってことだから、注意した方がいい。

入れられるものは、決まっている。
意図しないモノは、入れてはダメなのです。
違うと分かっていて、きゅうりやナス、人参を突っ込んではいけないのです。

nullは?

型でダメなら、異常な型だけど万人受けする奴はどう?ってことで、nullを入れてみる。

    var list = new ArrayList<String>();
    list.add(null);
    System.out.println(list.get(0).getClass());
    System.out.print(list);

型指定あっても大丈夫だから、たぶん、コンパイルエラーにはならないと予想。
たぶん、実行時にヌルポ

$ javac TestJEP286.java

$ java TestJEP286
Exception in thread "main" java.lang.NullPointerException
        at TestJEP286.main(TestJEP286.java:7)

予想通り、コンパイルは通って、実行時にヌルポ。
言っとくけど、試す前に予想してますからね。

やっぱりnullの特殊性が際立つんですよね、Javaって。
どの言語でもそうだけど、特殊な値は、挙動が似通っているから、どこかの言語で覚えれば、だいたい通用する。

途中で別のインスタンスにしてみる

もう、入れるモノを変えるのは飽きたので、入れ物の方を変えてみる。

    var list = new ArrayList<String>();
    list = new ArrayList<Integer>();
    list.add("test");
    System.out.println(list.get(0).getClass());
    System.out.print(list);

大丈夫そうな気がしないでもない。
直してコンパイル&実行してみる。

$ javac TestJEP286.java
TestJEP286.java:6: エラー: 不適合な型: ArrayList<Integer>をArrayList<String>
に変換できません:
    list = new ArrayList<Integer>();
           ^
エラー1個

初期化した時の型と違うから、怒られた。。。
考えたら、初期化したときの型は、変えられないから、当然といえば当然か。
これは、var 使わない場合も一緒ですね。

継承関係にあるとどうなるか

クラス設計で必須となる、継承関係が有効に働くのか一番気になったので確認。
確認は、以下のソースで。

import java.util.*;

class TestJEP286_2 {
  public static void main(String[] args) {
    var list = new ArrayList<SuperInteface>();
    list.add(new SubInterface1());
    list.add(new SubInterface2());
  }
}

interface SuperInteface {
}

class SubInterface1 implements SuperInteface {

}

class SubInterface2 implements SuperInteface {

}

予想は、問題なくコンパイル&実行できる。

$ javac TestJEP286_2.java

$ java TestJEP286_2

とくに出力してないので、味気ない感じ。。。
予想通り、ちゃんとコンパイル&実行できましたね。

互換性があれば、突っ込んでも問題ないということですね。
だからと言って、きゅうりやナス、人参を突っ込んではダメです。

感想

型を書かなくても良くなっただけで、なくなったわけではない。
型チェックは従来と一緒になる。
型が見えない分、分かりやすく、直感的なメソッド名や変数名を付けないとダメ。
そして、それはいい方向に向かうと、信じてる。

従来の知識は、ちゃんと活きてくるので、怖がらずに使ったほうがいいと思いました。

あと、ちゃんと実装が間に合ってるので、安心はしている。
リリースサイクル変わって、1発目の目玉機能がダメですは、洒落にならないからな。

他のヤツも、あとで確認したい。

雑記

とりあえず試したけど、IDEの予測変換が使えないようなので、久々にゼロからタイピングしたのが辛かった。
VisualStudioCode使ってみたけど、案外、Javaでもいい感じにコーディングできるんだなって印象だった。
動作も軽快だったし。
EclipseからIntelliJに行こうかと思ったけど、VisualStudioCodeでもいいかな~って最近思ってる。
業務で使っているTypescriptの実装にも使っているのがデカい。
久々に使うと、全然ショートカット使えずに焦るんだよね。。。