タイトル: 変数
SEOタイトル: Java 変数完全ガイド(プリミティブ / 参照 / final / var / スコープ)
| この記事の要点 |
- Java の変数はプリミティブ型(int/long/double 等 8 種)と参照型(クラス / 配列)の 2 系統
- 宣言と初期化:
int x = 10;。インスタンス変数はデフォルト値あり、ローカル変数はデフォルト値なし(未初期化使用はコンパイルエラー) - スコープはブロック単位
{ }。同名変数を内側で再宣言不可 var(Java 10+, JEP 286 LVTI)でローカル変数の型推論。インスタンス変数では使えないfinal で定数化。static final がクラス定数(命名は SCREAMING_SNAKE_CASE)
|
変数の基本
// 宣言 + 初期化
int x = 10;
String name = "taro";
double price = 1980.0;
// 宣言と初期化を分離
int y;
y = 20;
// 同じ型を複数同時に
int a = 1, b = 2, c = 3;
// 定数 (final)
final int MAX_COUNT = 100;
// MAX_COUNT = 200; // ❌ コンパイルエラー
プリミティブ型 8 種
| 型 | サイズ | 範囲 | デフォルト値 |
boolean | 1 bit (実装依存) | true / false | false |
byte | 8 bit | -128 〜 127 | 0 |
short | 16 bit | -32768 〜 32767 | 0 |
char | 16 bit | 0 〜 65535 (UTF-16) | ' ' |
int | 32 bit | -2^31 〜 2^31-1(約 ±21億) | 0 |
long | 64 bit | -2^63 〜 2^63-1 | 0L |
float | 32 bit | IEEE 754 単精度 | 0.0f |
double | 64 bit | IEEE 754 倍精度 | 0.0d |
参照型とプリミティブの違い
// プリミティブ: 値そのものを変数が持つ
int a = 10;
int b = a; // 値コピー
b = 20;
System.out.println(a); // 10(a は影響なし)
// 参照型: ヒープのオブジェクトへの参照
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1; // 参照コピー(同じ配列を指す)
arr2[0] = 99;
System.out.println(arr1[0]); // 99(同じ配列だから変わる)
// String は不変なので参照型でも値型のように振る舞う
String s1 = "hello";
String s2 = s1;
s2 = "world";
System.out.println(s1); // hello
変数の種類とスコープ
public class User {
// クラス変数 (static): クラスに 1 つ。デフォルト値あり
static int totalUsers = 0;
// インスタンス変数: インスタンスごと。デフォルト値あり
private String name;
private int age;
// 静的定数
public static final String DEFAULT_ROLE = "guest";
public void process() {
// ローカル変数: ブロック内のみ有効。デフォルト値なし
int count = 0;
for (int i = 0; i < 10; i++) {
// for のループ変数 i はループブロック内のみ
count += i;
}
// System.out.println(i); // ❌ コンパイルエラー: i はここでは見えない
if (count > 30) {
String message = "high"; // if ブロック内のみ
}
// System.out.println(message); // ❌ エラー
}
}
var による型推論 (Java 10+, JEP 286)
// Java 10+ LVTI (Local Variable Type Inference)
var name = "taro"; // String
var count = 10; // int
var list = new ArrayList<String>(); // ArrayList<String>
var map = Map.of("a", 1, "b", 2); // Map<String, Integer>
// for ループでも使える
for (var entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// ❌ できないこと
// var x; // 初期化必須
// var y = null; // 型推論不可
// var z = () -> 1; // ラムダの型推論不可
// public var field = 10; // フィールドでは不可
// var add(var x) {...} // メソッドの引数 / 戻り値では不可
final 変数
// 1. ローカル変数の final
final int MAX = 100;
// MAX = 200; // ❌ 再代入不可
// 2. インスタンス定数(コンストラクタで 1 度だけ代入可)
public class Order {
private final String id;
public Order(String id) {
this.id = id; // OK
}
}
// 3. static final = 真の定数(クラス定数)
public class Constants {
public static final int MAX_RETRY = 3;
public static final String SERVICE_NAME = "OrderService";
}
// 4. 参照型の final: 参照は変えられないが中身は変えられる
final int[] arr = {1, 2, 3};
arr[0] = 99; // OK
// arr = new int[5]; // ❌ 参照の付け替え不可
final List<String> list = new ArrayList<>();
list.add("hello"); // OK(List 自体は不変ではない)
命名規則
| 対象 | 命名 | 例 |
| クラス | UpperCamelCase | OrderService |
| 変数 / メソッド | lowerCamelCase | userName / getUserAge() |
| 定数 (static final) | SCREAMING_SNAKE_CASE | MAX_RETRY_COUNT |
| パッケージ | lowercase | com.example.order |
| 型パラメータ | 1 文字大文字 | T, E, K, V |
Auto Boxing / Wrapper クラス
// プリミティブ ↔ Wrapper の自動変換
int i = 10;
Integer boxed = i; // Auto Boxing: int → Integer
int unboxed = boxed; // Auto Unboxing: Integer → int
// Generics は参照型のみ → Wrapper 必須
List<Integer> nums = new ArrayList<>();
nums.add(10); // Auto Boxing
// 落とし穴: Integer の比較は equals
Integer a = 200;
Integer b = 200;
System.out.println(a == b); // false(参照比較)
System.out.println(a.equals(b)); // true
Integer c = 100;
Integer d = 100;
System.out.println(c == d); // true(-128〜127 は IntegerCache)
他言語との違い
| 項目 | Java | PHP | JavaScript |
| 変数宣言 | 型必須 or var | $ 接頭辞、型自由 | let / const / var |
| 型チェック | 静的(コンパイル時) | 動的 | 動的 (TypeScript で静的) |
| 定数 | final / static final | const / define() | const |
| スコープ | ブロック | 関数(PHP 7+ で if/for もブロック類似) | let/const はブロック、var は関数 |
| 初期化必須 | ローカル変数のみ | 不要 | 不要 |
FAQ
Q: var はいつ使うべき?
A: 初期化式で型が自明な場合(var list = new ArrayList<String>();)に推奨。可読性が下がる長い式や数値リテラルは型を明示するのが無難。
Q: ローカル変数のデフォルト値はなぜ無い?
A: 「未初期化のまま使うバグ」を防ぐため、コンパイルエラーで検出する設計です。インスタンス変数はオブジェクト生成時に初期化保証されます。
Q: int と Integer、どちらを使うべき?
A: 高速 / null 不要なら int、null 表現や Collection 格納が必要なら Integer。DB null マッピングは Integer がよい。