java11のvarの注意点
java11のvarの注意点
java 10 から、javaのローカル変数に、ローカル変数型推論が追加されました。
このローカル変数型推論は、Java SE 11 Programmer I の試験(いわゆる、java Silverと呼ばれている試験)の試験内容チェックリストにも含まれています。
すでに同試験は配信開始されており、今後の試験では出題されることが予想されます。
こちらの 記事 たち で、varを使った宣言の方法を紹介しました。
宣言以外にも、 javaでvarを扱う際にはいくつか注意が必要 なので、本記事ではそれらをまとめて忘備録代わりにメモ。
本記事も、ひしだまのホームページ(外部リンク)様のこちらの記事を参考に手元の環境で試した内容をもとに執筆しております。
また、本記事の内容は執筆時の環境で確認した内容です。今後のバージョンアップなどで、仕様や動作が変わる可能性があります。
なお、varを使った変数宣言の方法は↓をご覧ください。
javaの環境について
javaの環境は以下の通りです。
javaのバージョン
openjdk version “11” 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
javac 11
プログラムを実行する際は自己責任で実行してください。
以上、お約束のやつ終わり!
それでは早速行ってみよう!
注意点
『ローカル』変数型推論
あくまでも『ローカル』変数型推論です。 インスタンス変数(フィールド)の宣言時には使えません 。
public class Hoge{ //var field = "hello"; //インスタンス変数なのでコンパイルエラー }
うっかりやらないように注意(゜∀゜)
変数名にvarが使える
筆者が試したバージョンでは、varはkeywordではなく、「reserved type name(予約された型名)」となっています。したがって varという変数名の変数を定義可能 です。
int var = 1; //OK
Silverの試験が好きそうなネタですね(゜∀゜)
きちんと代入まで行っていれば、以下のようにデータ型と変数名の両方をvarで記述することもできます。
var var = 1; //OK
でもややこしいからよい子はマネしちゃだめだ(゜Д ゜)
メソッド名にvarが使える
変数名同様、 varというメソッド名のメソッドを定義可能 です。
void var(){ } //OK
これもSilverの試験が好きそうなネタですね(゜∀゜)
でもクラス名にはvarは使えない
「reserved type name(予約された 型名 )」なので、 クラス名にvarは使えません 。
class var{ } //コンパイルエラー
ですので、java 10 以降の環境は、java 9 以前の環境に対する互換性は厳密には、なくなっています。
が、普通var何て名前のクラス名つけない、よね。。?そもそもクラス名は大文字始まりが慣例 モガモガ
メソッドの引数にも使えない
メソッドの引数には、ローカル変数型推論は使えません 。void method(var v){ //←ここでコンパイルエラー System.out.println(v); }
それは、ジェネリクスの仕事や(゜Д ゜)
参考:メソッドの定義時ではなく、使用時に引数のデータ型を決めたい場合は、ジェネリクスを使って記述します。
<T> void method(T val){ System.out.println(val); }
ちなみにジェネリクスも、型推論の一種なんやで(゜∀゜)
でもラムダ式の引数には使える
ラムダ式の引数には、varを利用することができます 。Predicate pre = (var v) -> v.toString().equals("Hello");
だってラムダ式はそもそも型推論してるんだもん♪(゜∀ ゜)
参考:ラムダ式の引数のデータ型は省略可能
Predicate pre = (v) -> v.toString().equals("Hello");
そもそもデータ型書かなくても動くじゃん(゜Д ゜)
メソッドの戻り値にも使えない
メソッドの戻り値には、ローカル変数型推論は使えません 。var method(){ } //←ここでコンパイルエラー
これも、ジェネリクスの仕事や(゜Д ゜)
参考:メソッドの定義時ではなく、使用時に戻り値のデータ型を決めたい場合も、ジェネリクスを使って記述します。
<T> T method(T val){ return val; }
ジェネリクスすげぇ(゜∀゜)
データ型は変わらない
javaのローカル変数型推論は、変数の 宣言時にデータ型が推論 されます。 実行中に随時データ型を推測していくわけではありません 。
var v = 1; //この時点で変数vのデータ型が確定する //v = "Hello"; //代入しようとしているデータ型が宣言時と異なるのでコンパイルエラー
javaは、あくまでも(いわゆる)コンパイル言語。
データ型は変わらないその2
javaのローカル変数型推論は、変数の 宣言時にデータ型が推論 されます。その際のデータ型はあくまでも 代入の右辺から判断されます 。
var vList = new ArrayList<Integer>(); //vListはArrayList<Integer>型 //vList = new ArrayList<Object>(); //ArrayList<Object>型は代入できない。
これは当然でしょ(゜∀゜)
データ型は変わらないその3
javaのローカル変数型推論は、変数の 宣言時にデータ型が推論 されます。その際のデータ型はあくまでも 代入の右辺から判断されます 。
例え同じ親クラスから派生していても、 異なるデータ型を代入しようとするとコンパイルエラー です。
//var vList = new ArrayList<Integer>(); //vList = new LinkedList<Integer>();
javaでは兄弟姉妹は赤の他人・・・(゜Д ゜)
上記のようなコードを書きときは、きちんとデータ型を記述しましょう。
List list = new ArrayList<Integer>(); list = new LinkedList<Integer>();
データ型は変わらない 匿名クラス編
「javaのvarの使い方 ラムダ式編」でも扱った通り、ローカル変数型推論の宣言時に 匿名クラスを用いた場合、再代入ができません 。
var f = new Runnable(){ @Override public void run(){ System.out.println("f1.run()"); } }; /* //匿名クラスを再度実装して代入するとコンパイルエラー f = new Runnable(){ //コンパイルエラー @Override public void run(){ System.out.println("f1.run()#2"); } }; */
でも、匿名クラスを代入した変数に再代入なんて、しない、よね。。。?(^^;
データ型は変わらない ラムダ式編
javaのvarの使い方 ラムダ式編でも扱った通り、ローカル変数型推論の宣言時に キャストを使ってラムダ式を代入している場合、再代入可能 です。
var f = (Runnable)() -> System.out.println("f3.run()"); //ラムダ式での場合、再代入可能。 f = (Runnable)() -> System.out.println("f3.run()#2");
Goldの試験とかで出そうだなぁ※あくまで個人の感想です。
他にも気づいたことがあったら足していこう♪
以上、javaでローカル変数型推論(var)を利用する場合の注意でした♪
javaのローカル変数型推論の宣言方法は↓をチェック!!
オススメ!!→ java 11 の問題はこちら オススメ!!→ java のローカル変数型推論(var)の使い方はこちら オススメ!!→ java 8 の問題はこちら オススメ!!→ javaのプログラム作成練習問題はこちら オススメ!!→ java関連の記事はこちら