Java10
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の実装にも使っているのがデカい。
久々に使うと、全然ショートカット使えずに焦るんだよね。。。