Javaのvarとは? Java超初心者の勉強

2020-12-13

Javaでvarが使えるようになりました。(Java SE 10から)。
使い方がよくわかていないので調べてみました。
奥が深すぎるので、追いきれていない部分もあるかと思いますがお手柔らかに。

※ Java11の仕様で調べて書いています。

varとは

varは「variable type (変数型)」でローカル変数を宣言時に型を明示的にかかなくても型を推測してくれます。

明示的に型を宣言せずに型が推論されることを型推論(type inference)と呼びます。
Javascriptのvarやletと同じで馴染みがある方も多いのではないでしょうか。

varのメリット

  • ボイラープレートコードを書くことを避けれる
  • 冗長するコードを減らすことができる
  • 上記のことからコードが読みやすくなる

書き方

var型を使わない書き方

String str = "Programmer Life";

var型を使った場合

// var 変数名 = 値;
var str = "Programmer Life";

右辺の情報から型を推論しString型として扱われます。

varは予約された型名

varは予約語(keyword)ではなく予約された型名(Reserved Type name)です。

予約語ではない

var int = "Hello"; // intは予約後なので使えないのでコンパイルエラー
var var = "Programmer Life" // varは予約後ではないので使用は可能

予約された型名である

public class var {} // varは使えない
public class Var {} // Varなら使用可能

varの特徴

宣言時に型を指定しないため以下の特賞があります。

変数は必ず初期化する

varで型を宣言した場合、 宣言時に必ず値を代入し初期化しなければいけません。 

var str = "" ; // 初期化OK
var str; // コンパイルエラー

nullは代入できない

nullの場合、型を推測することができないためコンパイルエラーとなります。

var str = null ; // コンパイルエラー

異なる型を代入できない

var str ="10";
str = 10; // コンパイルエラー

String型からint型に変換できないためエラーとなります。

インスタンス変数には使えない (ローカル変数のみ)

public class Test1{
    var str1 =""; // コンパイルエラー (メンバー変数)
    void test() {
        var str2 =""; // ローカル変数 OK
    }
}

※ローカル変数はクラスに宣言されている変数(メンバー変数)でなくメソッドから参照される変数のこと。

アクセス修飾子はつかない

public var str = "Programmer Life"; // コンパイルエラー(無効な修飾子)

finalをつけることは可能です。

配列は型を明記

var arr1[] = {"Hello"}; // コンパイルエラー(推論できない)
var arr2 = new int[3]; // OK int型と明記
var arr3 = new int[]{1,2,3}; // OK int型と明記

メソッドの引数に使用できない

void disp(var v) {} // コンパイルエラー(許可されていない)

匿名クラス

 var obj2 = new Supplier() {
    //メソッドをオーバーライド
    @Override
    public Integer get(){
        return 10;
    }
};

※ java.util.function.Supplierをimportしてテストしてください。

匿名クラスについてよくわからない方は以下も合わせてご確認ください。

ラムダ式

var sup1 = () -> 10; // コンパイルエラー 型が推論できない
var sup2 = (Supplier)() -> 10; // OK Supplierの型でキャスト
var con = (Consumer)(var s) ->{ System.out.print(s);}; // OK ラムダ式の引数にvarは使用可能

※ java.util.functionをimportしてテストしてください。

ラムダ式についてよくわからない方は以下もあわせてご確認ください。

よく見るvarの使われどき

ジェネリクスの省略

Map<String, List<Integer>> phoneBook = new HashMap<String, List<Integer>>(); // Java SE 6
Map<String, List<Integer>> phonebook = new HashMap<>(); // Java SE 7
var map = new HashMap<>(); // Java SE 10

よく見かけるのはMap、次いでArrayListでした。ジェネリクスが省略されてだいぶすっきり見やすくなっています。型名を変数名に書いて工夫している人もいました。

拡張for文

var varList = List.of(1,2,3);
for(var v : varList){
    System.out.print(v);
}

Listのvarを拡張for文でまわす、Listを拡張for文でまわすなどよくみかけます。
JavaSE11 Silverの問題でよく引っかかります。

おわり

他にもラムダ式でも使われているのもよく見かけます。これからの機能にvarは使われることが多いかもしれませんね。
以前、知り合いに今から10年以上Javaをやっている人に立ち向かうなら新しいことを覚えて飛び越えていったほうが早いと聞いたことがあります。新しい機能(Java10ももう古いかもしれませんが)はチャンスかもしれないですね。

varはまだあまり馴染みがないようで職場で使用されているのは見たことはありませんが、Javaは日々変化し使いやすくなっているんですね。

参考

Java 10 LocalVariable Type-Inference
Java SE 9: “var” for local variables
【ローカル変数型推論】java11のvarの注意点【java11】

Java

Posted by Nakamoto