変数の定義の全体像
Java で「変数の定義」は、値にラベルを貼ってプログラム中で再利用できるようにする作業です。基本形は「型 名称 = 値;」で、型が先に来るのがポイントです。たとえば int age = 20; のように書くと、age は整数を入れる箱として使えます。定義だけして後で値を入れるなら、int count; count = 1; と段階を分けても構いません。コンパイラは型に基づいてチェックするため、型は「契約」であり、誤用を早期に防いでくれます。
基本の書き方と初期化
宣言と代入の基本形
最もよく使う形は「宣言と初期化を同時に行う」書き方です。例えば double price = 1999.5; や boolean isMember = true; のように、型に合わせたリテラルを入れます。宣言だけ行った変数は、初期化前に使うとコンパイルエラーになります。これは未初期化の値による不具合を防ぐための仕組みで、Java が安全志向であることの表れです。
例と注意点
char grade = 'A'; のように文字はシングルクォートで表現します。文字列はオブジェクトなので String name = "Tanaka"; のようにダブルクォートを使います。整数の大きさが足りない場合は long を使い、リテラルに L を付けます(例: long big = 10000000000L;)。初期化は「意図した型で」行うのが大切で、誤った型の値は代入できません。
基本型と参照型の違い(深掘り)
基本型(プリミティブ)とは
int, long, double, float, boolean, char, そして符号付き 2/1/8 バイトの short/byte が「基本型」です。これらは値そのものを直接保持し、メモリ効率と速度に優れます。数値計算やフラグ管理などで頻繁に用います。double は一般的な小数計算に適しますが、通貨のような誤差が許されない計算には BigDecimal を使います。
参照型(オブジェクト)とは
String, 配列、独自クラス、List や Map などは「参照型」で、変数はオブジェクトへの参照(ポインタのようなもの)を保持します。String は不変(immutable)で、一度作った内容は変わりません。大量連結や編集には StringBuilder を使うと効率が良くなります。この違いを理解しておくと「なぜ同じ代入でも挙動が違うのか」を説明できます。
型変換と数値の落とし穴(深掘り)
暗黙の拡張と明示の縮小
小さい型から大きい型への変換(例: int → long)は暗黙に許されますが、大きい型から小さい型への変換(例: long → int)は明示的キャストが必要です。キャストは情報が失われる可能性があるため、縮小時は必ず意味を理解して使いましょう。
整数割り算とオーバーフロー
5 / 2 は整数割り算のため結果は 2 になります。小数が欲しければどちらかを double にします(例: 5 / 2.0 → 2.5)。また、int の計算は範囲を超えるとオーバーフローし、結果が循環します。大きな積や累積を扱うときは long を選ぶ、もしくは必要なら BigInteger を検討します。誤差や溢れの可能性を事前に見積もるのが安全なコーディングの鍵です。
スコープ、final、var の使い分け
スコープ(有効範囲)
変数は宣言されたブロック { ... } の中だけ有効です。外に出ると参照できません。スコープを意識して「必要最小限の範囲」で宣言すると、名前の衝突や誤用を防げます。メソッドの引数もメソッド内のスコープに属し、他からは見えません。
final(再代入禁止)
final を付けると「再代入不可」になります(例: final int port = 8080;)。初期化は一度だけ可能です。不変にできるものを final にすることで、意図しない書き換えを防ぎ、コードの信頼性が上がります。参照型の final は「参照の再代入が禁止」であり、オブジェクトの内部状態まで不変になるわけではない点に注意してください。
var(ローカルの型推論)
Java 10 以降ではローカル変数に var が使えます(例: var msg = "hello"; → 型は String に推論)。読みやすさが損なわれる場合は明示型を使い、初学者は「API の型を学ぶために最初は明示型」をおすすめします。var はローカル変数限定で、フィールドやメソッド引数、戻り値には使えません。
実用例で身につける
例 1: 変数の宣言・初期化・再代入
public class Basics {
public static void main(String[] args) {
int count = 1;
double rate = 1.25;
String title = "Java";
count = count + 2; // 再代入
title = title + " Basics"; // String は新しい文字列が生成される
System.out.println(count); // 3
System.out.println(rate); // 1.25
System.out.println(title); // "Java Basics"
}
}
Javaこの例では、整数・小数・文字列を宣言し、再代入で値が更新される様子を確認できます。String の連結は新しいオブジェクトを作るため、繰り返し連結では StringBuilder を使うと効率的です。
例 2: 型変換と整数割り算の注意
public class CastingDemo {
public static void main(String[] args) {
int a = 5;
int b = 2;
System.out.println(a / b); // 2(整数割り算)
System.out.println(a / (double)b);// 2.5(明示的に小数へ)
long big = 1_000_000_000L;
int small = (int) big; // 縮小キャスト、値が収まるか要注意
System.out.println(small);
}
}
Javaこの例は、整数割り算の挙動とキャストの必然性を示します。演算結果の型を意識することで、意図しない切り捨てを防げます。
例 3: final と StringBuilder の使い分け
public class ImmutableDemo {
public static void main(String[] args) {
final String base = "Java";
// base = "New"; // コンパイルエラー(final 再代入不可)
StringBuilder sb = new StringBuilder(base);
for (int i = 0; i < 3; i++) {
sb.append("!");
}
System.out.println(sb.toString()); // "Java!!!"
}
}
Javafinal は再代入を防ぎ、StringBuilder は繰り返し編集に適しています。不変性と可変性を適材適所で使い分けるのが設計の基本です。
設計の視点からのアドバイス(重要ポイントの深掘り)
Java の変数は「型で意図を伝える」道具です。計算なら基本型、複雑な振る舞いなら参照型(クラス)を選ぶのが近道です。初期化は「妥当な初期値を必ず入れる」、範囲は「狭いスコープに閉じる」、変更可能性は「変える必要がないものは final」を徹底すると、バグの温床が一気に減ります。数値計算の精度と範囲は常に意識し、通貨は BigDecimal、大きな整数は BigInteger のように適切な型を選びましょう。
