ニコニコ大百科モバイル

7/2(月)よりスマホまたはPCでアクセスした場合、各デバイス向けのサイトへ自動で転送致します


var(Java)


ヨミ: ジャバノカタスイロンサレルヘンスウセンゲン

var(Java)とは、Java 10で導入された、型推論を伴った変数宣言を示す新予約である。


概要


2018年3月Java 10がリリースされた。文法上の最大の変更点は、これまで変数宣言にはの記載が必須であったところを、ローカル変数についてはvarを用いることによりの記載を省略できるようになったことである。

varはvariable(変数) の略である。

class内でフィールド定するときには用いることは出来ない。


型推論


上述のように、これまでJava変数宣言にはの記載が必須であった。

ArrayList<String> strings = new ArrayList<String>();

これについては"ArrayList<String>"が2回出てきて冗長であるという批判が以前からあった。Java 7からジェネリクスの型推論が導入されて、以下のように書けるようになった。

ArrayList<String> strings = new ArrayList<>();

これにより"String"の重複はなくなったが、"ArrayList"の重複はなくなっていない。今回のvarの導入により、以下のように書くことができる。

var strings = new ArrayList<String>();

賛否とガイドライン


今回の変更については、コードを短くできる(今更この程度短くしても焼け石に)という肯定的な意見と、変数名にvarを使った古いコードがたくさんあるオワタ右辺の自明でない時にコードを理解しづらくなるという否定的な意見がある。

この点についてJavaリファレンス実装であるOpenJDK(Oracleではない)公式サイト内で以下のようなガイドラインが出されている。

以下で上記ガイドライン中の見出しを元に解説する。


原則


  1. コードは書くことよりも読むことの方が大事だ。
  2. コードの意味はその周囲を見るだけで明らかであるべきだ。
  3. コード可読性IDE依存すべきではない。
  4. の明示とvarの使用は一長一短。

ガイドライン


G1. 変数名に有用な情報を含める

情報変数名に含めてしまえば、省略してしまって構わないということ。

var stringArrayList = value;

なお、この方式はハンガリアン記法と呼ばれ、一般にはあまりよい方法とはされていない。だいたい、変数名に名を含めるのであれば名の重複をなくすという的に反しており、本末転倒ではないか。varを使うためにハンガリアン記法を用いるのではなく、情報変数名に含めたほうが適切な場合にvarの使用を考慮するということ。

G2. ローカル変数のスコープを最小限にする

何らかの事情により右辺を変更することになって右辺のが変わった場合、従来であれば左辺の宣言を変更する必要があり、その際に変数が変わったことに気づくことができる。

しかし、varを用いると左辺は自動的に型推論が変更されるので気づくことが出来ない。

この対策として、ガイドラインではvarで宣言された変数が使用される場所を最小限に(察するに、変数宣言と同じ画面に表示される範囲(よりもっと近く)に)とどめるよう推奨している。

コードは始めは変数の宣言と使用場所が離れていなくても、良を重ねているうちに間に色々追加されて離れていくということは多々ありそうだが、ガイドラインでは変数のスコープが大きくなってしまう時は、スコープが小さくなるように修正できた時のみvarを使用することと書かれている。ガイドラインによるとスコープが大きくなってしまうのはコードが悪いので修正すべきということのようである。

G3. 初期化子が読者に十分な情報を提供する時にvarの使用を考慮する

代表的なのが、概要で述べた右辺がコンストラクタの場合である。コンストラクタは名がそのまま用いられるので、左辺の名が省略されても、が分からなくなることはない。

ガイドラインでは他の例として、Files.newBufferedReader()やList.of("a", "b", "c")のように右辺に何らかの形での名前が混じっている場合などを挙げている。

G4. メソッドチェーンで長くなった式や、入れ子の式を分解するときにvarを使用する

コードの「見栄え」に関する話である。原文の事例を見たほうがいかもしれない。

Java 8でStreamが導入されてから、メソッドチェーンを用いる機会が増えた。

Streamの終端操作で得られたCollectionからさらにStreamを生成してメソッドチェーンを続けることは、文法上可だが、途中に終端操作が入っていることがわかりづらいので、分割が推奨される。見づらい入れ子の式も同様に分割することが推奨される。

この際、を明示すると、名の長さがまちまちの場合に、右辺の開始位置に大きな段差が生じて醜い。varの導入により、この段差が軽減(なくなりはしない)される。インデントのやり方を変えれば済むような気もする。

G5. 「宣言型は具象クラスでなくインターフェースで」の原則にはこだわり過ぎない

varが導入されるはるか昔から、Javaでは宣言のインターフェースで行うことが推奨されている。

宣言の右辺がArrayListでも、Listとしてしか使用しない場合はListで宣言することが推奨される。(たとえば、なんらかの事情で右辺がLinkedListに変わってしまった場合でも他のコードを書き直す必要がないからとされている。)

varで宣言すると、インターフェースコンストラクタを持たないので、右辺はインターフェース実装した具クラスになり、インターフェース変数宣言することはできなくなり、上記原則に反してしまう。

G2に従っているならvarで宣言された変数はそこから数行以内で使用されるはずであり、変更の影が外に及ぶことはないから許容されるというのがガイドラインの見解である。

G6. ダイヤモンド演算子やジェネリクスとvarを組み合わせるときは注意

たとえば、概要で述べた例を引数まで省略してしまうと、以下のようになる。

var strings = new ArrayList<>();

右辺はStringのArrayListであるとわからなくなってしまうので、ArrayList<Object>と型推論される。

G7. リテラルとvarの組み合わせにも注意

short shortNumber = 0;
var shortNumber = 0;

上の行ではshortNumberのshortだが、下の行ではshortNumberのintになる。

(余談だが、右辺がnull;の時はが定まらないのでエラーになる。)


関連項目



外部リンク



最終更新日: 18/04/18 23:22
タグ検索 パソコン版を見る


[0]TOP
ニコニコ動画モバイル
運営元:ドワンゴ