Javaのvarとは、Java 10から導入された「ローカル変数型推論」の機能です。
String message = "Hello"; の型名を省略し、var message = "Hello"; と書けます。ジェネリクスなど型名が長い場面で威力を発揮します。
ただし使いどころを誤ると可読性が下がり、チーム開発では「var禁止」ルールが設けられることもあります。
この記事を読めば、(1) varが使える場面・使えない場面、(2) 使うべきか判断する基準、(3) varが「禁止」される現場の理由と対処法が分かります。
Java歴12年の私が実務で培った使い分けのコツも交えて解説します。
この記事でわかること
- varが使える場面・使えない場面の全パターン
- メリット・デメリットを踏まえて使うべきかを判断する基準
- varが「禁止」される現場の理由と対処法
PARTS LIST /目次
Javaのvarとは?型推論が導入された背景
var は、Java 10から導入された「ローカル変数型推論」のための機能です。
変数を宣言する際に、型の代わりに var と記述すると、コンパイラが初期化の値から自動的に型を判断(推論)してくれます。
varの導入によって、Javaが動的型付け言語になったわけではありません。あくまでコンパイル時に型が決定される静的型付け言語である点は、今までとまったく同じです。
コードの記述量を減らし、より現代的なプログラミングスタイルを可能にするために導入されました。
varが使えるようになったバージョン(Java 10)
var は、2018年にリリースされた Java 10で JEP 286(Local-Variable Type Inference)として正式に導入されました。2026年時点で、導入から約8年が経過しています。
そのため、Java 9以前の環境では使用できません。
長期サポート(LTS)バージョンであるJava 11から本格的に普及しました。
2026年現在のLTS最新版であるJava 25(2030年9月までの標準サポート)でも、varは当然サポートされています。今やvarは多くのプロジェクトで標準的に使われる機能です。
これからJavaを学ぶ方は、必ず押さえておきましょう。
型推論(type inference)の仕組み
型推論は、決して難しい仕組みではありません。コンパイラが、代入される値(右辺)を見て、変数の型(左辺)を「賢く推測してくれる」機能です。
例えば、以下のコードを見てみましょう。
// 従来の書き方
String message = "Hello, Java!";
// varを使った書き方
var message = "Hello, Java!";
var を使った場合、コンパイラは右辺の "Hello, Java!" が文字列リテラルであることから、変数 message の型を String であると自動的に判断します。
プログラマが明示的に String と書かなくても、コンパイル後のコードは全く同じものになるのです。
var list = new ArrayList<String>();ArrayList<String>varとJavaScriptのvarの違いに注意
var というキーワードから、JavaScriptを連想する方もいるかもしれません。
しかし、Javaの var とJavaScriptの var は全くの別物なので注意が必要です。
-
Javaのvar
- 静的型付けです。一度型が決まったら、あとから別の型の値は代入できません。
- 型推論はコンパイル時に行われます。
var message = "こんにちは"; // messageはString型に確定
message = 123; // コンパイルエラー! String型にintは代入できない
-
JavaScriptのvar
- 動的型付けです。同じ変数に異なる型の値を再代入できます。
var message = "こんにちは"; // messageはstring型
message = 123; // エラーにならない! messageはnumber型になる
JavaとJavaScriptのvarの違いを理解しておかないと、思わぬバグの原因になります。
var message = "こんにちは";Stringstringmessage = 123;Javaの var は、あくまで型宣言を省略するためのシンタックスシュガー(糖衣構文)であると覚えておきましょう。
varは予約語(キーワード)ではない
意外に思われるかもしれませんが、varはJavaの予約語(keyword)ではありません。正確には「予約型名(reserved type name)」に分類されます。
そのため、以下のように変数名として var を使うこと自体はコンパイルエラーになりません。
// 変数名として使える(非推奨)
int var = 10; // OK: varはint型変数として宣言される
// String var = "hello"; // 同一スコープでは再宣言不可(別スコープならOK)
// 型推論としても使える
var message = "Hello"; // これはローカル変数型推論
Java Silver等の資格試験では「varは予約語か?」という出題もあるため、知識として押さえておくと安心です。
注意
変数名にvarを使うのは可読性を著しく損なうため、実務では絶対に避けましょう。
Java varの基本的な使い方
varの基本的な使い方は、宣言と同時に初期化する・nullで初期化しない・ローカル変数にのみ使うという3つのルールを守るだけです。
宣言と初期化のルール
var を使うには、3つのルールを守る必要があります。以下の3点は必ず押さえてください。
- 宣言と同時に初期化が必須。
varは右辺の値から型を推論するため、宣言するだけでは型が決まらず、コンパイルエラーになります。
var message; // NG! 初期化されていないため型が推論できない
message = "Hello";
- nullでの初期化はできない。nullはどの参照型にも代入できる特殊な値です。そのため、nullだけでは具体的な型を推論できず、エラーになります。
var user = null; // NG! nullから型は推論できない
- ローカル変数にしか使えない。varが使えるのは、メソッド内やforループ内などのローカル変数に限られます。クラスのフィールド(メンバー変数)やメソッドの引数、戻り値の型としては使用できません。
varで使える場面と使えない場面
var はどこでも使えるわけではありません。使える場面と使えない場面を、コード例と共に整理します。
- ローカル変数の宣言
public void processData() {
var name = "Taro Yamada"; // String型
var age = 25; // int型
var userMap = new HashMap<Integer, String>(); // HashMap<Integer, String>型
}
var userList = List.of("Taro", "Hana", "Jiro");
for (var user : userList) {
System.out.println(user.toUpperCase());
}
- try-with-resources文
try (var reader = new BufferedReader(new FileReader("file.txt"))) {
// ファイル読み込み処理
} catch (IOException e) {
e.printStackTrace();
}
【使えない場面】
- フィールド(インスタンス変数、クラス変数)
public class User {
private var name = "Taro"; // NG! フィールドには使えない
}
- メソッドの戻り値
public var getUserName() { // NG! メソッドの戻り値には使えない
return "Taro";
}
- メソッドの引数
public void printMessage(var message) { // NG! メソッドの引数には使えない
System.out.println(message);
}
- ラムダ式(Java 10まで)Java 10では使えませんでしたが、Java 11以降はvarが使えます(詳細は後述のJEP 323セクション参照)。
配列・ジェネリクスでのvar利用例
var は、特に型名が長くなりがちなジェネリクスや配列で真価を発揮します。コードがすっきりと読みやすくなるのが分かります。
- ジェネリクスでの利用:
ArrayListやHashMapのような、ジェネリクスを使った複雑な型宣言がとてもシンプルになります。右辺の型定義は省略できない点に注意してください。
// 従来
Map<String, List<Map<Integer, String>>> complexData = new HashMap<>();
// varを使用
var complexData = new HashMap<String, List<Map<Integer, String>>>();
- 配列での利用: 配列の宣言も
varで行えます。配列の場合も、右辺でnew int[]のように型の明示が必要です。
// 従来
int[] numbers = {1, 2, 3, 4, 5};
// varを使用
var numbers = new int[]{1, 2, 3, 4, 5};
IDEでvarの推論型を確認する方法
varで宣言した変数の型が分からなくなったら、IDEの機能で簡単に確認できます。
IntelliJ IDEAでは変数にカーソルを合わせるだけで推論された型がポップアップ表示されます。Eclipseでもホバーで同様に確認可能です。
コード上で型を確認したい場合は、getClass()メソッドが使えます。
var list = new ArrayList<String>();
System.out.println(list.getClass().getName()); // java.util.ArrayList
varを使ってもコンパイル後の型は明確に決まっているため、実行時にはいつでも正確な型情報を取得できます。
IDEと合わせて活用すれば、varによる型の見えにくさは十分に解消できます。
varとfinal varの組み合わせ
モダンなJava開発では、再代入しない変数にfinalを付ける習慣が推奨されています。
varとfinalを組み合わせることで、型宣言を省略しつつ再代入を防止できます。
// final var: 型推論 + 再代入不可
final var maxRetry = 3;
final var userName = getUserName();
// 再代入しようとするとコンパイルエラー
// maxRetry = 5; // NG! finalなので再代入できない
実務ではfinal varを積極的に使うのがおすすめです。変数が変更されないことが保証されるため、コードの安全性と可読性が向上します。
Java 11:ラムダ式引数でvarが使える(JEP323)
Java 11では、JEP 323によりラムダ式の引数にもvarが使えるようになりました。
通常のラムダ式と動作は同じですが、引数にアノテーションを付けたいときに便利です。
// Java 11以降: ラムダ式の引数にvarが使える
// アノテーションを付けたいときに便利
(@Nonnull var x, @Nullable var y) -> x.process(y);
// 通常のラムダと同等(型推論される)
(var x, var y) -> x + y;
// 注意: varと型名の混在は不可
// (var x, int y) -> x + y; // NG! var・型名・省略は混在できない
ラムダ引数でvarを使う場合は、全ての引数をvarにしてください。varと明示的な型名や型の省略を混在させると、コンパイルエラーになります(varを使わない場合は、全引数に型名を書くか、全て省略するかのどちらかです)。
Java varは使うべき?メリット・デメリットから判断する
varは便利な機能ですが、良い面ばかりではありません。メリットとデメリットを正しく理解し、場面に応じて使い分けることが、保守性の高いコードにつながります。
varでコードが簡潔になるメリット
最大のメリットは、コードの記述量が減り、見た目がすっきりする点にあります。
私のプロジェクトでは、Spring BootのService層にvarを導入した際、1メソッドあたり平均2〜3行のコード削減効果がありました。
特にDI(依存性の注入)で複数のサービスを受け取る箇所や、Stream APIの中間変数で効果が大きく、コードの見通しが明らかに改善しました。
特に、前述のジェネリクスのように型名が長くなる場合、var を使うことでコードの水平方向のスペースが削減され、変数名やロジックそのものに集中しやすくなります。
// ※ Stream.toList() は Java 16 以降の機能。Java 11 では .collect(Collectors.toList()) を使う
// 長いクラス名やジェネリクスで効果絶大
var inputStream = new FileInputStream("data.bin");
var userRankingMap = new TreeMap<Integer, List<User>>();
// メソッドチェーンの結果を受ける場合も見やすい
var filteredUsers = userList.stream()
.filter(u -> u.getAge() >= 20)
.toList();
冗長な型宣言を省略できるため、コードの可読性が向上し、開発効率もアップします。
varで可読性が下がるケース
一方で、varの乱用はコードの可読性を著しく低下させる危険性をはらんでいます。
例えば、以下のようなコードはどうでしょうか。
var result = dataProcessor.execute();
このコードだけでは、変数resultの型がすぐに分かりません。型を知るにはexecute()メソッドの定義までジャンプしなければなりません。
コードを読む人にとって大きな負担です。
右辺から型が自明でない場合や、ビジネスロジック上、型の情報そのものを読み手に伝える必要がある場合には、var を使うべきではありません。
チーム開発での注意点
個人開発であれば自分の判断で使えますが、チームで開発を進める上では、var の使い方についてコーディング規約を設けましょう。
ポイント
- どのような場面で
varの使用を許可するか - どのような場面では明示的な型宣言を必須とするか
こうしたルールをチームで共有しておかないと、人によって書き方がバラバラになります。結果として、コードベース全体の可読性やメンテナンス性が下がります。
「var を使っても良いが、変数名で型が推測できるようにする」といった共通認識を持つだけでも、品質は大きく変わります。
varが「禁止」される現場の理由と対処法
実務では、コーディング規約でvarの使用を禁止しているプロジェクトも存在します。主な理由は以下の3つです。
- コードレビューの負荷増大: レビュアーが型を推測する手間が増え、見落としリスクが上がる
- Java 8以前のプロジェクトとの統一: チーム内でJavaバージョンが混在する場合、書き方を揃えるために禁止される
- 初心者が多いチームでの混乱防止: 型を意識する習慣が身についていない段階で
varを許可すると、可読性が急激に下がる
ただし、全面禁止よりも「newで型が明らかな場合のみ許可」といった部分的なルールのほうが現実的です。
PMD(UseExplicitTypesルール)やIntelliJ IDEAのインスペクション機能で、許可範囲外のvar使用を自動検出することもできます。
私の経験では、var禁止ルールは「チームの習熟度に応じて段階的に緩和する」のがベストです。
最初は右辺new時のみ許可し、慣れてきたらStream API等にも拡大する運用がスムーズでした。
Java varのベストプラクティス|使いどころの判断基準
java var を効果的に使いこなし、コードの品質を高めるための実践的なベストプラクティスを3つ紹介します。
適切な変数名で型を推測しやすくする
var を使う際の絶対的なルールは、変数名から型や役割が明確に推測できるように命名することです。
型情報が省略される分、変数名が持つ意味の重要性が格段に増します。
【悪い例 】var list = getUsers(); // Listであることは分かるが、何のリストか不明
var data = findById(1); // dataの中身が全く分からない
【良い例 】
var userList = getUsers(); // ユーザーのリストであることが明確
var targetUser = findById(1); // 探している特定のユーザーだと分かる
varを使う場合は特に変数名の命名を意識しましょう。
varと明示的な型宣言の使い分け
「いつ var を使い、いつ明示的な型を使うべきか」を、具体的な場面で確認しましょう。
var を積極的に使うべき場面】
-
右辺で
newを使っており、型が完全に明らかな場合
var user = new User("Taro");
var idList = new ArrayList<Integer>();
- キャストの右辺など、型が自明な場合
var user = (User) obj;
- 中間変数を一時的に格納する場合: メソッドチェーンの途中結果など、その場でしか使わない変数には
varが適しています。
- 右辺から型が推測しにくい場合
// var result = getProcessingResult(); だと型が不明
ProcessingResult result = getProcessingResult();
- インターフェース型で受けたい場合: 実装クラスではなく、より抽象的なインターフェースで変数を扱いたい場合は、明示的に型を宣言します。インターフェース型で宣言しておくと、実装クラスを差し替えてもコードを変更せずに済みます。
// ArrayListではなく、より汎用的なListとして扱いたい
// var names = new ArrayList<String>(); と書くと、namesの型はArrayListになる
List<String> names = new ArrayList<>();
私も過去に、varを使った変数に曖昧な名前を付けてコードレビューで指摘されたことがあります。
var data = service.execute(); と書いたところ、「dataの中身が何なのかメソッド定義を見に行かないとわからない」と。
それ以降、varを使う際は「変数名だけで型と役割が伝わるか」を自分にチェックリストとして課しています。varを使うなら、命名に3倍気を使う。
varを使うなら命名に3倍気を使う、というのが私の12年の実務で得た実感です。
実際のプロジェクトでの活用例
実際のプロジェクトでは、Stream APIと組み合わせる場面で var が頻繁に登場します。
// ※ Stream.toList() は Java 16 以降の機能。Java 11 では .collect(Collectors.toList()) を使う
public List<String> getActiveUserEmails(List<User> users) {
// Stream APIの中間操作でvarを活用
var activeUsers = users.stream()
.filter(User::isActive)
.toList(); // activeUsersは List<User> 型
// 別の処理...
var userEmailMap = activeUsers.stream()
.collect(Collectors.toMap(User::getId, User::getEmail));
// さらに処理を続ける...
var sortedEmailList = userEmailMap.values().stream()
.sorted()
.toList();
return sortedEmailList;
}
複数の処理ステップに分ける際に、その都度生まれる中間的なコレクションを var で宣言すると、コードの流れが追いやすくなります。
もう一つ、Spring Bootでの実例を見てみましょう。REST APIの戻り値を受け取る場面では、varの効果が特に大きくなります。
// Before(var導入前)— 1行が長くなる
ResponseEntity<List<UserProfileDto>> response = restTemplate.exchange(
url, HttpMethod.GET, entity,
new ParameterizedTypeReference<List<UserProfileDto>>() {});
// After(var導入後)— 型宣言が消えてすっきり
var response = restTemplate.exchange(
url, HttpMethod.GET, entity,
new ParameterizedTypeReference<List<UserProfileDto>>() {});
右辺のParameterizedTypeReferenceで型が明らかなため、左辺のResponseEntity<List<UserProfileDto>>は冗長です。
varを使えば、型の重複が解消されてコードが読みやすくなります。
なお、Spring Boot 4.1系(2026年8月時点の最新)でもRestClientが推奨されており、varとの相性の良さは同様です。
よくある質問
Javaのvarについて、読者からよく聞かれる質問をまとめました。使える場所・使うべきかの判断・禁止理由など、本文で扱った論点を中心に回答しています。細かい手順や根拠は各見出しの本文もあわせて確認してください。
Q1. Javaのvarとは何ですか?
A1. varは、Java 10(2018年リリース)で導入されたローカル変数型推論の機能です。変数宣言時に型名を省略し、右辺の値からコンパイラが型を自動判断します。動的型付けではなく、あくまでコンパイル時に型が確定する静的型付け言語のままです。
Q2. varは予約語ですか?
A2. いいえ、varは予約語(keyword)ではなく「予約型名」に分類されます。そのため変数名としてvarという名前を使うこと自体はコンパイルエラーになりませんが、可読性を著しく損なうため実務では避けるべきです。
Q3. varは使うべきですか?
A3. 右辺から型が明らかな場合(newを使った生成時など)は積極的に使うべきです。逆に、メソッドの戻り値を受ける変数など右辺から型が推測しにくい場合は、明示的な型宣言を使うべきです。判断基準は「読み手にとって親切かどうか」です。
Q4. varを禁止しているプロジェクトがあるのはなぜですか?
A4. コードレビューの負荷増大、Java 8以前のプロジェクトとの書き方統一、初心者が多いチームでの可読性低下防止という3つの理由が主です。全面禁止よりも「型が明らかな場合のみ許可」という部分的なルールの方が現実的です。
Q5. final varとvarの違いは何ですか?
A5. final varは型推論に加えて再代入を禁止する組み合わせです。通常のvarは再代入可能ですが、final varで宣言した変数は宣言後に値を変更しようとするとコンパイルエラーになります。再代入しない変数には積極的に使うのがおすすめです。
Q6. varで宣言した変数の型はどうやって確認できますか?
A6. IntelliJ IDEAやEclipseなどのIDEでは、変数にカーソルを合わせるかホバーするだけで推論された型がポップアップ表示されます。コード上で確認したい場合はgetClass().getName()メソッドを使う方法もあります。
Q7. varはメソッドの引数や戻り値にも使えますか?
A7. いいえ、使えません。varが使えるのはローカル変数のみで、フィールド(インスタンス変数)、メソッドの引数、戻り値の型には使用できません。ただしJava 11以降はJEP 323により、ラムダ式の引数にはvarを使えます。
まとめ:Java varの使いどころと注意点
java var を使いこなし、より良いコードを目指しましょう。
varは便利だが「万能」ではない
var は、Javaのコードをより簡潔で読みやすくするための強力なツールです。特に、型名が長くなる場面では絶大な効果を発揮します。
しかし、varが便利であることは「常に var を使うべき」という意味ではありません。
可読性を下げる可能性があることを常に念頭に置き、「読み手にとって親切かどうか」を基準に、明示的な型宣言と使い分けることが大切です。
初心者がつまずきやすいポイント
Javaを学び始めた方が var でつまずきやすいのは、主に以下の2点です。
ポイント
- 何でも入る型だと誤解してしまう:
varは静的型付けであり、一度決まった型は変更できません。JavaScriptの感覚で使わないようにしましょう。 - 使えない場所で使おうとする:
varはローカル変数専用です。フィールドやメソッドの引数・戻り値には使えないルールをしっかり覚えてください。
私もJavaを学び始めたころ、JavaScriptのvarと同じ感覚で「型なんて自動で決まるんでしょ」と思い込んでいた時期がありました。
フィールド変数にvarを書いてコンパイルエラー、nullで初期化してエラー……と連続で引っかかりました。「型推論とはそういうものではない」と理解するまでに、丸1日かかった記憶があります。
今後のJava開発での位置づけ
2026年現在、Javaは半年ごとのリリースサイクルを継続しています。
2026年3月にJava 26、2026年9月にJava 27がリリースされました。
varは2018年のJava 10導入から約8年が経過し、varを前提としたコーディングスタイルはすでに多くの現場で定着しました。
今後、var を適切に使いこなすスキルは、生産性の高いJavaエンジニアにとって必須のものとなるでしょう。
ぜひあなたのプロジェクトでもvarを活用してみてください。
| REV. | DATE | 内容 |
|---|---|---|
| 6 | 2026-10-16 | 図解を描き直し(図面のデザインにそろえた) |
| 5 | 2026-10-14 | 経歴の表記を修正し、一人称をそろえた。雰囲気だけの挿絵を外した |
| 4 | 2026-10-12 | 2026年10月時点の情報で全体を見直し |
| 3 | 2026-08-29 | 2026年8月時点の情報で全体を見直し(古い記述を3件更新) |
| … ほか1回の改訂 | ||
| 1 | 2025-09-15 | 初版 |
varを使っている箇所を1つ見直してみましょう。変数名だけで型と役割が伝わるか、チェックしてみてください。
続きを追う:X(@Tom_Java_Tech) / RSS
途中経過は、また書きます。








