【Java】クラス変数とは?インスタンス変数との違いもわかりやすく解説

Java

今回の記事ではJavaのクラス変数について解説していきます。
Javaでは変数にstaticをつけることで、クラスをインスタンス化することなく、その変数を使うことができます。
この変数のことをクラス変数といいます。

そしてstaticを使っていない変数のことをインスタンス変数といいます。このインスタンス変数はクラスをインスタンス化した後でなければ使うことができません。

今回の記事ではクラス変数とインスタンス変数について次のような順番で解説していきます。

  • クラス変数とは?
  • インスタンス変数とは?
  • クラス変数とインスタンス変数の違い
  • クラス変数の注意点と使い所

変数の違いを知っておくことで必要な変数を必要な場所で宣言することができます。
コーディングの幅も広がりプログラマーとして1ランクアップすることができるので、ぜひ違いを理解できるようにしましょう!
初心者の方でも理解できるようにわかりやすく解説しますので、ぜひ最後まで読んでくださいね!

最速で稼ぐ」を目指すエンジニアリングスクールRaiseTech!まずは無料説明会に参加!

クラス変数はstaticのついた変数

クラス変数は「static」をつけて宣言される変数のことです。「static」で宣言するためstatic変数と呼ばれることもあります。
そのクラスから作られるすべてのインスタンスで共有される変数です。

クラス変数はクラスに紐づいているため、インスタンス化しなくてもアクセスすることができます。
基本的な宣言方法は次のようになります。

アクセス修飾子 static 型 変数名

クラス変数の呼び出し方2つ

では実際のプログラムでクラス変数を確認してみましょう。
クラス変数には呼び出し方が2つあるので、2つとも確認しておきましょう。

クラス名.変数名

まずは「クラス名.変数名」でアクセスする方法です。
次のプログラムを確認してください。

public class TestVariable {

	public static void main(String[] args) {
		// クラス変数にアクセスして、値を代入する
		Test.classValiable = "クラス変数に代入した値";

		// クラス変数に代入した値を出力する
		System.out.println(Test.classValiable);
	}
}

class Test {
	// クラス変数の宣言
	public static String classValiable;
}

Testクラスの中で「static」を使ったクラス変数「classValiable」を宣言しています。
mainメソッド内で「Test.classValiable」でクラス変数にアクセスして値を代入することができます。

実行すると次のように、クラス変数にアクセスできていることがわかります。

クラス変数に代入した値

インスタンス名.変数名

クラス変数には「インスタンス名.変数名」でもアクセスすることが可能です。
次のプログラムを確認してください。

public class TestVariable {

	public static void main(String[] args) {

		// Testクラスのインスタンスを生成
		Test test = new Test();

		// インスタンスを使って、クラス変数に値を代入
		test.classValiable = "インスタンスを使って代入";
		// クラス変数の出力
		System.out.println(test.classValiable);

	}
}

class Test {
	// クラス変数の宣言
	public static String classValiable;
}

はじめにTestクラスのインスタンス「test」を作成しています。
その後「test.classValiable」でクラス変数にアクセスすることができています。

実行すると次のよう結果です。

インスタンスを使って代入

インスタンスを使ってクラス変数にアクセスする方法を解説してきましたが、こちらの方法はあまりおすすめではありません。
理由は後に解説しますが、特に理由がない場合はクラス名を使ってクラス変数にアクセスするようにしましょう。

インスタンス変数とは?

インスタンス変数は各インスタンスで固有の値となります。
newを使って、インスタンスを生成した時に変数領域が確保されます。
クラス変数はクラスで共通の値でしたが、インスタンス変数の値はインスタンス毎に異なります。

「インスタンスって何?」
「インスタンス化がよくわからない」
という方はこちらの記事を参考にしてみてください。

インスタンス変数のサンプルプログラム

インスタンス変数のサンプルプログラムです。

public class TestVariable {

	public static void main(String[] args) {

		// Testクラスのインスタンスを生成
		Test test = new Test();

		// インスタンスを使って、インスタンス変数に値を代入
		test.instanceValiable = "インスタンス変数に値を代入";
		// インスタンス変数の出力
		System.out.println(test.instanceValiable);

	}

}

class Test {
	// クラス変数の宣言
	public static String classValiable;

	// インスタンス変数の宣言
	public String instanceValiable;
}

Testクラスにインスタンス変数のinstanceValiableを宣言しました。
mainメソッド内でTestクラスのインスタンスを作成し、値を代入しています。
値が代入されているか確認するために出力した結果は次のようになります。

インスタンス変数に値を代入

以上がインスタンス変数の解説となります。

クラス変数とインスタンス変数の違い

次にクラス変数とインスタンス変数の違いについてプログラムを動かしながら、確認していきます。

まずクラス変数ですが、クラス変数はクラスで共通の値を保持します。そのため、1つのインスタンスを使って値を変更した場合、他のインスタンスの持っているクラス変数も変更されることになります。

逆にインスタンス変数の場合は、インスタンス固有の値となります。そのため1つのインスタンスで値を変更しても、他のインスタンスは変更の影響を受けません。

次のプログラムを確認してください。
社員を表す「Employee」クラスを作成しました。
このEmployeeクラスは次の変数を持ちます。

  • クラス変数の「会社名」
  • インスタンス変数の「社員名」
class Employee {
	/**
	 * クラス変数:会社名
	 * すべてのインスタンスで共有される
	 */
	public static String companyName;

	/**
	 * インスタンス変数:社員名
	 * それぞれのインスタンスで別の値を持つ
	 */
	public String employeeName;
}

上記のEmployeeクラスを使ってクラス変数とインスタンス変数の違いを確認します。
次のmainメソッドをざっと確認してください。細かい解説は後ほどしていきます。

public static void main(String[] args) {

	// 社員クラスのインスタンスを2つ作成
	Employee taro = new Employee();
	Employee hanako = new Employee();

	// 社員クラスの会社名を設定
	Employee.companyName = "株式会社uhablog";

	// 各社員の名前を設定
	taro.employeeName = "太郎";
	hanako.employeeName = "花子";

	// 各社員の情報を出力
	System.out.println("太郎の情報");
	System.out.println("会社名 = " + taro.companyName);
	System.out.println("名前 = " + taro.employeeName);
	System.out.println("花子の情報");
	System.out.println("会社名 = " + hanako.companyName);
	System.out.println("名前 = " + hanako.employeeName);
	System.out.println();

	// 会社名を変更
	Employee.companyName = "有限会社uhablog";

	// 各社員の会社名を出力
	System.out.println("会社名を変更");
	System.out.println("会社名 = " + taro.companyName);
	System.out.println("会社名 = " + hanako.companyName);
	System.out.println();

	// 太郎の名前を変更
	taro.employeeName = "次郎";

	// 名前の出力
	System.out.println("太郎の名前を変更");
	System.out.println("名前 = " + taro.employeeName);
	System.out.println("名前 = " + hanako.employeeName);

}

まず最初にmainメソッドでは次のような処理を行っています。

  1. Employeeクラスのインスタンスを2つ作成する
  2. Employeeクラスのクラス変数:会社名を変更 → この会社名は2つのインスタンスで共通
  3. 各インスタンスの名前を設定する → ここで設定した名前はそれぞれのインスタンス毎に違う
  4. 社員情報の出力

この時点で出力される情報は次のようになります。
会社名は2つとも同じ値で、社員名は2つで違う値であることが確認できます。

太郎の情報
会社名 = 株式会社uhablog
名前 = 太郎
花子の情報
会社名 = 株式会社uhablog
名前 = 花子

次の処理の解説に移ります。

  1. 会社名を変更する
  2. 各インスタンスの会社名を出力

会社名を一度だけ変更しました。
しかし会社名はクラス変数であるためすべてのインスタンスで共有されます。
そのため2つのインスタンスで両方とも値が変わっていることがわかります。

会社名を変更
会社名 = 有限会社uhablog
会社名 = 有限会社uhablog

最後に次の処理を行います。

  1. 1つのインスタンスだけ社員名を変更する
  2. 各インスタンスの社員名を出力する

1つだけ社員名を変更しました。
社員名はインスタンス変数であるため、一方の値を変更したからといって、別のインスタンスの値が変わることはありません。

太郎の名前を変更
名前 = 次郎
名前 = 花子

以上がクラス変数とインスタンス変数の違いです。
クラス変数はどこかで値を書き換えてしまうと他にも影響が出るということは覚えておきましょう。

クラス変数の注意点と使い所

注意点

クラス変数はどこかで値を書き換えると他のインスタンスでも値が変わってしまいます。
なので、あまり無闇に値を変えないほうが良いです。
というか、クラス変数の値を変えなければいけない状況になること自体があまりよろしい状態ではないので、クラスの構成とか設計を見直すようにしたほうが良いかもしれません。

また「インスタンス名.クラス変数」でも値の変更をすることができますが、これは危険だと述べました。
この書き方でクラス変数を書き換えていると一見インスタンス変数を書き換えていると勘違いが起こるからです。バグの原因になりますので、クラス変数を書き換えるときは「クラス名.クラス変数」で書き換えるようにしましょう。

使い所

「書き換えてはいけないなんて、クラス変数はどこで使われるんだい?」という疑問をお持ちの方がいるかもしれません。
答えとしては定数などシステム内で共通してずっと使いたい値を入れておく場合によく使われます。

例えば開発しているシステムで「エラーが起きたときは共通のメッセージを画面に表示したい」とします。
このとき各機能毎にエラーメッセージを手打ちしているとどこかで誤字をしてしまうことがあるでしょう。またエラーメッセージを一斉に変更したいとなった場合、各機能の出力箇所をすべて変更する必要があります。
これは非常にめんどくさいですが、一つクラス変数を定義しておいて、そのクラス変数を参照してエラーメッセージを出力するようにしておけば誰かが誤字をしてしまうことも各機能のメッセージを修正する必要もなくなります。

このような場合にクラス変数が使われることが多いです。

まとめ

今回の記事ではクラス変数とインスタンス変数について解説してきました。

クラス変数は「static」をつけた変数のことで、クラスをインスタンス化しなくても利用することができます。
またそのクラスから作られたインスタンス全てで同じ値が共有されます。
どこかでクラス変数の値を変えてしまうと、他のインスタンスのクラス変数も変わってしまうということは覚えておきましょう。

インスタンス変数は「static」をつけていない変数のことで、クラスをインスタンス化しなければ利用することができません。
このインスタンス変数は各インスタンスで値を管理するので、他のインスタンスで値を変えたからといって影響はありません。

以上がクラス変数とインスタンス変数の違いになります。
最速で稼ぐ」を目指すエンジニアリングスクールRaiseTech!まずは無料説明会に参加!

コメント

タイトルとURLをコピーしました