はじめに
さて今回は、Javaにおけるクラス変数、インスタンス変数、ローカル変数の違いについてまとめたいと思います。
つい最近仕事をする中で、「この変数はクラス変数じゃなくてインスタンス変数にしておいた方が良い」といった話を聞きました。
案の定Javaに対する知識が全くない私にとっては何が何だかさっぱり・・・だったので調べて理解した内容を忘れないよう備忘録的に残しておきます。
それでは見ていきましょう~
クラス変数、インスタンス変数、ローカル変数の違い
ざっくりですが、「どこで宣言されるか」、「誰が共有するか」が大きく異なるポイントです。
もう少し細かい違いを表で見てみましょう。
| 種類 | 宣言場所 | 共有範囲 | 自動初期化 | 主な用途 |
|---|---|---|---|---|
| クラス変数 | クラス内 | 全インスタンスで共有 | 型ごとのデフォルト値が自動設定 | 共通データ |
| インスタンス変数 | クラス内 | インスタンスごと | 型ごとのデフォルト値が自動設定 | オブジェクトの状態 |
| ローカル変数 | メソッド内 | そのメソッドのみ | 必ず自分で初期化 | 一時的な処理 |
クラス変数、インスタンス変数で自動的に設定される値は以下です。
| 型 | 初期値 |
|---|---|
| int | 0 |
| double | 0.0 |
| boolean | false |
| String | null |
クラス変数(static変数)

クラス変数、またの名をstatic変数と呼ぶらしいですが、以下のような特徴があります。
- staticを付けて宣言する
- 全てのインスタンスで共有される
- クラスが読み込まれたときに1つだけ作られる
- クラス名からアクセスできる
ちなみに「static」とは、”クラスに属しインスタンスを作らなくても利用できる”という意味です。
ゲームを例にとって具体的にイメージしてみましょう。
例えばクラス変数は、ゲームの中で「現在ログインしているプレイヤー数」です。これらはどのプレイヤーから見ても変わらない変数ですよね?
要するにゲーム全体で1つだけ持っておくような値をクラス変数とします。
<コード例>
class Player {
static int playerCount = 0; // クラス変数
String name;
Player(String name) {
this.name = name;
playerCount++; // プレイヤー作成時に人数を増やす
}
}「playerCount」がプレイヤーの人数です。最初にstatic intで宣言し、初期値として”0″をセットしています。(自動設定されますが、もちろん意図的にセットしてもOKです。)
「name」という変数はプレイヤーの名前で、各プレイヤー毎に付けられるようになってますね。
Player(String name)が処理に当たりますが、引数で指定した名前を変数にセットし、合わせてプレイヤー作成時に人数を増やしています。
<使用例>
public class Main {
public static void main(String[] args) {
Player p1 = new Player("勇者");
Player p2 = new Player("魔法使い");
System.out.println(Player.playerCount);
}
}使用例はこんな感じです。
“勇者”と”魔法使い”を作っています。
<実行結果>
2プレイヤーの人数を確認すると、”2″となっていますね。当然のことながら、”勇者”と”魔法使い”がいるからです。
<イメージ>
ゲーム全体
│
└ playerCount = 2
↑
全員共有
Player p1
└ name = 勇者
Player p2
└ name = 魔法使いインスタンス変数

インスタンス変数は以下のような特徴があります。
- クラスの中で宣言
- staticを付けない
- インスタンスごとに別の値を持つ
- オブジェクトの状態を表す
具体例でイメージしましょう。
<コード例>
class Player {
String name;
int hp;
}例えば、キャラクター毎の”名前”や”HP”がインスタンス変数にあたります。オブジェクト毎(キャラクター毎)に別の値を持つわけですね。
<使用例>
Player hero = new Player();
hero.name = "勇者";
hero.hp = 100;
Player mage = new Player();
mage.name = "魔法使い";
mage.hp = 80;
System.out.println(hero.hp); // heroのHPを出力する
System.out.println(mage.hp); // mageのHPを出力する上記では、「hero」というプレイヤーを定義し、名前を”勇者”に、HPを”100″にしています。
また、「mage」というプレイヤーは、名前を”魔法使い”に、HPを”80″にしています。
<実行結果>
100
80セットした通りの値が出力されていますね。ゲームの中で全部共通というわけではなく、”勇者”は”勇者のHP”、”魔法使い”は”魔法使いのHP”を持っていることが分かります。
<イメージ>
Player hero
├ name = 勇者
└ hp = 100
Player mage
├ name = 魔法使い
└ hp = 80ローカル変数

ローカル変数は以下のような特徴があります。
- メソッドの中で宣言
- そのメソッド内でしか使えない
- メソッド終了で消える
- 初期化しないと使えない
具体例でイメージしましょう。
<コード例>
class Player {
void attack() {
int damage = 10;
System.out.println("ダメージ:" + damage);
}
}attackメソッドは攻撃処理です。
「int damage = 10」が攻撃で与えられるダメージを表しているわけで、これはattackメソッドの中だけで使われます。
<使用例>
Player hero = new Player();
hero.attack();
hero.attack();heroというオブジェクトを作成し、attackメソッドを2回呼び出しています。
<実行結果>
ダメージ:10 // 1回目の処理結果
ダメージ:10 // 2回目の処理結果単純に、「ダメージ:10」が2回出力されているだけに見えますが、処理の流れをイメージすることが重要です。
① 1回目の「hero.attack();」でattackメソッドを呼び出す
② 「damage = 10」となり、damageに10がセットされる
③ 「ダメージ:10」と出力される
④ メソッドが終了し、damageにセットした値が消える ← ★ここが重要
⑤ 2回目の「hero.attack();」でattackメソッドを呼び出す
~~~以下繰り返し~~~
上記のように、damageにセットした10という値は、メソッドが終わるとともに値が削除されます。これがローカル変数の特徴です。
<イメージ>
attack()
damage = 10
↓
ダメージ表示
↓
メソッド終了
↓
damage消えるなぜ使い分けが必要なのか?

結論から言うと、使い分けが必要な理由は大きく以下の3点です。
- データの役割が違うから
- 不要なデータ共有を防ぐため
- 不要なメモリ使用を防ぐため
- 一時データを安全にするため
それぞれ細かく見ていきましょう。
1. データの役割が違うから
ゲームには次のように役割の違うデータがあります。
| データ | 役割 | 種類 |
|---|---|---|
| プレイヤー人数 | ゲーム全体の情報 | クラス変数 |
| HP | キャラクターごとの情報 | インスタンス変数 |
| 攻撃ダメージ | 一時的な計算 | ローカル変数 |
これをすべて同じ種類の変数で扱うとプログラムが分かりにくくなってしまうので、それぞれ適切な変数で役割を持たせているわけですね。
2. 不要なデータ共有を防ぐため
もしすべての変数が共有されると、困ったことが起きます。
例えば、HPをクラス変数にしてみましょう。
class Player {
static int hp;
}そしてプレイヤーを作ります。
Player hero = new Player();
Player mage = new Player();
hero.hp = 100;
mage.hp = 50;こうすると結果は、
hero.hp = 50
mage.hp = 50となってしまいます。
勇者のHPは100にしたはずが、その次にある魔法使いのHPを50にする処理を実行してしまうことで、HP(全体で共通しているクラス変数)が書き換えられてしまいます。
これは困ったことですよね。キャラクター毎に固有のHPを持てなくなってしまいます。
3. 不要なメモリ使用を防ぐため
もし全てをインスタンス変数にすると、今度は逆の困ったことが起きます。
例えばゲーム設定です。
class Game {
int maxLevel = 100;
}ゲームの最大レベルが100という設定ですね。この上で、もしGameオブジェクトを1000個作った場合、
maxLevel = 100
maxLevel = 100
maxLevel = 100
...と同じデータが1000個作られます。これはどう考えても無駄です。そのため、ゲーム全体で共通しているデータを1つとして持っておこうというわけです。
4. 一時データを安全にするため
攻撃ダメージのような値は、「計算 → 使用 → 終了」だけでよいです。もしこれをインスタンス変数にすると、
class Player {
int damage;
}damage = 10といったように、攻撃もしていないのに古い値が残る可能性があります。そのため、一時的な値はローカル変数とします。
最後に
さて今回は、Javaにおけるクラス変数、インスタンス変数、ローカル変数の違いについてまとめました。
具体例も交えたのでイメージしやすかったのではないでしょうか?
また、なぜ使い分けが必要なのかの理由も理解してもらえてたら嬉しいです。
| 持ち主 | 変数 |
|---|---|
| クラス | クラス変数 |
| オブジェクト | インスタンス変数 |
| メソッド | ローカル変数 |
以上!
前回まとめた記事も読んでもらえると嬉しいです!
Java以外の勉強記事も是非!





コメント