var(Java)とは、Java 10で導入された、型推論を伴った変数宣言を示す新予約語である。
2018年3月にJava 10がリリースされた。文法上の最大の変更点は、これまで変数宣言には型の記載が必須であったところを、ローカル変数についてはvarを用いることにより型の記載を省略できるようになったことである。
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ではない)公式サイト内で以下のようなガイドラインが出されている。
型情報を変数名に含めてしまえば、型を省略してしまって構わないということ。
var stringArrayList = value;
なお、この方式はハンガリアン記法と呼ばれ、一般にはあまりよい方法とはされていない。だいたい、変数名に型名を含めるのであれば型名の重複をなくすという目的に反しており、本末転倒ではないか。varを使うためにハンガリアン記法を用いるのではなく、型情報を変数名に含めたほうが適切な場合にvarの使用を考慮するということ。
何らかの事情により右辺を変更することになって右辺の型が変わった場合、従来であれば左辺の型宣言を変更する必要があり、その際に変数の型が変わったことに気づくことができる。
しかし、varを用いると左辺は自動的に型推論が変更されるので気づくことが出来ない。
この対策として、ガイドラインではvarで宣言された変数が使用される場所を最小限に(察するに、変数宣言と同じ画面に表示される範囲(よりもっと近く)に)とどめるよう推奨している。
コードは始めは変数の宣言と使用場所が離れていなくても、改良を重ねているうちに間に色々追加されて離れていくということは多々ありそうだが、ガイドラインでは変数のスコープが大きくなってしまう時は、スコープが小さくなるように修正できた時のみvarを使用することと書かれている。ガイドラインによるとスコープが大きくなってしまうのはコードが悪いので修正すべきということのようである。
代表的なのが、概要で述べた右辺がコンストラクタの場合である。コンストラクタは型名がそのまま用いられるので、左辺の型名が省略されても、型が分からなくなることはない。
ガイドラインでは他の例として、Files.newBufferedReader()やList.of("a", "b", "c")のように右辺に何らかの形で型の名前が混じっている場合などを挙げている。
コードの「見栄え」に関する話である。原文の事例を見たほうが早いかもしれない。
Java 8でStreamが導入されてから、メソッドチェーンを用いる機会が増えた。
Streamの終端操作で得られたCollectionからさらにStreamを生成してメソッドチェーンを続けることは、文法上可能だが、途中に終端操作が入っていることがわかりづらいので、分割が推奨される。見づらい入れ子の式も同様に分割することが推奨される。
この際、型を明示すると、型名の長さがまちまちの場合に、右辺の開始位置に大きな段差が生じて醜い。varの導入により、この段差が軽減(なくなりはしない)される。インデントのやり方を変えれば済むような気もする。
varが導入されるはるか昔から、Javaでは宣言の型はインターフェースで行うことが推奨されている。
宣言の右辺がArrayListでも、Listとしてしか使用しない場合はListで宣言することが推奨される。(たとえば、なんらかの事情で右辺がLinkedListに変わってしまった場合でも他のコードを書き直す必要がないからとされている。)
varで宣言すると、インターフェースはコンストラクタを持たないので、右辺はインターフェースを実装した具象クラスになり、インターフェース型で変数宣言することはできなくなり、上記原則に反してしまう。
G2に従っているならvarで宣言された変数はそこから数行以内で使用されるはずであり、変更の影響が外に及ぶことはないから許容されるというのがガイドラインの見解である。
たとえば、概要で述べた例を型引数まで省略してしまうと、以下のようになる。
var strings = new ArrayList<>();
右辺はStringのArrayListであるとわからなくなってしまうので、ArrayList<Object>と型推論される。
short shortNumber = 0;
var shortNumber = 0;
上の行ではshortNumberの型はshortだが、下の行ではshortNumberの型はintになる。
(余談だが、右辺がnull;の時は型が定まらないのでエラーになる。)
掲示板
掲示板に書き込みがありません。
急上昇ワード改
最終更新:2024/04/19(金) 14:00
最終更新:2024/04/19(金) 14:00
ウォッチリストに追加しました!
すでにウォッチリストに
入っています。
追加に失敗しました。
ほめた!
ほめるを取消しました。
ほめるに失敗しました。
ほめるの取消しに失敗しました。