薄給SEの技術屋日記

何でもポジティブに | 3人家族+チワワと暮らすSE | 20代は休む間も無く仕事と飲み会 | 30代から株主優待に目覚め今では節約しながら配当金投資 | 目標は配当金投資で住宅費月7万を補うこと | 大宮アルディージャサポ | 度重なる過労で体調不良となり家族と自分の身体を優先する生活 | 最近米国株の購入を開始

【Java】var「型推論」を使ってみよう

LOLIPOP

はじめに


最近Javaを触る機会が多かったのですが、Java1.4からの人間として育ったアラフォーのため、Java6を少しかじっている程度だと非常に効率が悪いことが分かり、少しずつ新機能を勉強していこうと思います。

java10~11の新APIを覚える


今回は型推論と呼ばれているvarというものを学んでいきたいと思います。
Javaは型制約が強く、左と右がしっかりと合っていないとコンパイルエラーや型が明確でないとIDEでは警告扱いになっていたと思います。どうも型「var」はJavascript等のスクリプト言語と同様に左側の型を意識することなく変数を定義できるようになるとのことです。





varを使ってみよう


右辺でインスタンス化している場合

// 右辺に型名がそのまま書いてあるので、何の型か一見してわかる
var dateTest = new Date();

var scannerTest = new Scanner(System.in);

var listTest = new ArrayList<String>();


すごいですね。今まできっちりと左側の型を明示的にしておく必要があったのにEclipse上で全く怒られません。

型推論とは


この「var」は型推論と呼ばれており、型を推測させる変数名で補ってあげる必要があります。
先ほどの変数名はDate型であれば変数名にdateを用いる、ArrayListであればlistを用いる等、明示的に変数で想定させるような書き方をしてあげる必要があります。そうでないと何の型が入っているのか全く分からなくなってしまいます。

IDEではきちんと型を把握している

ArrayListのvar変数を宣言しているとIDEArrayListだと認識しているので、アシスト内容もしっかり表示されます。全く問題なくコードは書けそうです。

var listTest = new ArrayList<String>();

listTest.add("a");
listTest.add("b");
listTest.add("c");


varをメソッドの引数定義に指定することはできない。
メソッドの引数の型をvarにしてみたら怒られました。そうですね。何でもありになっちゃうからこれはダメですよね。

/**
 * 型推論のメソッド定義・・・?
 * @param date
 */
public static void funcT(var date) {
}

varを引数に渡すことはできる。


これはギリギリOKでした。受け側のメソッド定義をvarの型が合っていればメソッドを呼び出す際にvarを渡すことは可能なようです。安心しました。

/**
 * テストメソッド
 * @param str
 */
public static void funcT1() {
    var str = "aaa";
    funcT2(str);
}

/**
 * テストメソッド
 * @param str
 */
public static void funcT2(String str) {
    System.out.println(str);
}

varを使用してメソッド内の内部メソッドを定義できる。


これは便利なのか?実際にすごい!と思いましたが、メソッド内にメソッドを簡単に定義できてもそれを外だしのprivateメソッド定義すればよいのではないか?と私は思ってしまうので、良い使い方があれば教えて欲しいです

public static void main(String[] args) {

    // func.capitalize() で呼び出せる
    // func はローカル変数なので、このメソッドの外からは呼べない
    var func = new Object() {
        private String capitalize(String s) {
            return s.substring(0, 1).toUpperCase() + s.substring(1, s.length()).toLowerCase();
        }
    };

    System.out.println(func.capitalize("tokyo")); // => Tokyo
    System.out.println(func.capitalize("TOKYO")); // => Tokyo
}

まとめ


varは型を定義しなくてよいのでコードがすっきりする。
IDEを使用すればコンパイルエラーになるようなこともない。
varを使うのであれば、プロジェクト全体でvar推奨にしないとおかしくなる。
メソッド内のメソッド定義はメリットが今のところ分からない。