Java初心者が押さえておきたい!変数の初期化ルールとベストプラクティス

こんにちは。ゆうせいです。
今回は「Javaにおける変数の初期化」について、初心者の方にもわかりやすく解説していきます。

Javaでは変数の初期化(=変数を使う前に値を入れておくこと)は非常に重要です。これを怠るとエラーになったり、予期しない動作をしてしまうことがあります。


Javaの変数の種類と初期化の基本ルール

まず最初に、Javaで使われる変数には大きく以下の3種類があります。

種類宣言される場所初期化の必要性
ローカル変数メソッドやブロック内必ず初期化が必要
インスタンス変数クラス内(staticでない)自動で初期値が代入される
クラス変数staticキーワード付き自動で初期値が代入される

ローカル変数の初期化

ローカル変数とは、メソッドの中などで一時的に使う変数のことです。

public void sampleMethod() {
    int sum;  // ローカル変数(初期化しないと使えない)
    sum = 0;  // 初期化
}

よくある初期化パターン

用途初期値理由
合計の計算0何も足さない状態が「0」だから
掛け算の計算1何も掛けない状態が「1」だから
最小値の比較Integer.MAX_VALUEどんな値とも比較できるようにする
最大値の比較Integer.MIN_VALUE同上

ローカル変数の未初期化はコンパイルエラー

以下のように初期化していないローカル変数を使うとエラーになります。

public void errorMethod() {
    int a;
    System.out.println(a);  // コンパイルエラー!
}


インスタンス変数の初期化

インスタンス変数は、クラスの外では static でないメンバ変数のことです。クラスがインスタンス化(new)されたときに自動で初期値が入ります。

自動的に入る初期値

データ型初期値
int, long0
float, double0.0
booleanfalse
char'\u0000'
参照型(配列、Stringなど)null
public class Person {
    int age;           // 0で初期化される
    String name;       // nullで初期化される
}

ですが!
明示的に初期化するほうが安全で読みやすいため、できる限り明示しておくのがベストです。


コンストラクタでの初期化

インスタンス変数に意味のある値を与えるには、コンストラクタを使って初期化するのが一般的です。

public class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;  // コンストラクタで初期化
        this.age = age;
    }
}

これならば、どのような値が設定されるのかが一目でわかりますね。

フィールドでの初期化

クラスの中で、変数を宣言すると同時に値を代入する方法を「フィールドでの初期化」と言います。
これはクラスのどのインスタンスも、常にその値からスタートするという場合にとても便利です。

例:

public class Person {
    String name = "匿名希望"; // nameを"匿名希望"で初期化
    int age = 20;            // ageを20で初期化
}

このように書くと、new Person()でインスタンスを生成したときに、
自動的に name"匿名希望" に、age20 になります。


フィールド初期化のメリット・デメリット

メリット:

  • 簡単に書ける
  • デフォルト値を明示できる
  • コンストラクタを書かなくてもいいケースがある

デメリット:

  • インスタンスごとに異なる初期値を設定できない
    → すべてのインスタンスで同じ値になってしまう

たとえば「ある人は20歳、ある人は35歳」といった使い方をしたいときには不便です。


コンストラクタでの初期化との違い

一方、コンストラクタでの初期化は、インスタンスごとに異なる値を与えたいときに使います。

コンストラクタを使った例:

public class Person {
    String name;
    int age;

    // コンストラクタ
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

これなら、次のように異なる初期値でオブジェクトを生成できます。

Person taro = new Person("太郎", 18);
Person hanako = new Person("花子", 25);


フィールド初期化とコンストラクタの併用

実はこの2つ、組み合わせて使うこともできます

public class Person {
    String name = "匿名希望"; // デフォルト値
    int age = 20;

    public Person(String name, int age) {
        this.name = name; // 引数で上書き
        this.age = age;
    }
}




なぜ併用するの?

  • コンストラクタを使わないときはデフォルト値を使う
  • 引数があれば、引数の値で上書きする

つまり、柔軟性がアップするというわけです!


表で整理:フィールド初期化とコンストラクタ初期化の違い

比較項目フィールド初期化コンストラクタ初期化
初期化のタイミングインスタンス生成時に自動コンストラクタ呼び出し時に手動
インスタンスごとの違い不可(すべて同じ値)可(異なる値を設定できる)
明示性高い(すぐ目に入る)意図がはっきりして保守しやすい
使用用途単純な固定値で十分なとき柔軟に設定したいとき

どっちを使えばいいの?

次のように使い分けるのがオススメです。

  • すべてのオブジェクトに同じ初期値を使いたい → フィールド初期化
  • インスタンスごとに違う値を設定したい → コンストラクタ初期化
  • 柔軟性を持たせたい → 両方を併用する

初期化しなくてよいケースはある?

以下のようなケースでは、初期化しなくても問題ありません。

インスタンス変数やクラス変数(static)は自動で初期値が設定される

ただし、そのまま使うのはおすすめしません
なぜなら、nullや0という初期値は意味のある値ではないことが多いからです。値を設定した人が意図的にそうしたのか、それとも放置してしまったのかがコードからはわからないのです。


少し高度な話:配列の初期化

配列も一括で初期化できます。

int[] scores = new int[5];  // 全要素が0で初期化される

配列の要素型によって初期値も変わります。

初期値
int[]各要素 0
boolean[]各要素 false
String[]各要素 null

初期化の注意点

例えば、合計値と平均を求めるコードでは次のように初期化します。

int sum = 0; // 合計を0で初期化
int count = 0;
double average = 0.0;

average = sum / (double)count;

平均の計算式は、

平均 = 合計 ÷ 件数

ですが、countが0のままだと「0で割る」ことになりエラーになるため、初期化だけでなく条件チェックも重要です。


まとめ:用途に応じた初期化を意識しよう!

用途初期値
加算0
掛け算1
最大値の判定Integer.MIN_VALUE
最小値の判定Integer.MAX_VALUE
配列の初期化型に応じた初期値

今後の学習の指針

変数のスコープとライフサイクルを学ぶことで、どのタイミングで初期化すべきかがもっとクリアになります。
例外処理(try-catch)との組み合わせで、初期化がどう影響するかにも注目してみてください。
・そしてぜひ、静的初期化子(static initializer)や初期化ブロックにも挑戦してみてください。

/

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。