1.はじめに
インスタンス変数とクラス変数の違いが曖昧だったので今後のためにまとめてみました。
参考になれば嬉しいです。
2.インスタンス変数とは
それぞれのインスタンスに属する変数となります。具体的には、newキーワードによってインスタンス変数領域(インスタンス)が確保され、初期値代入やコンストラクタ(インスタンス生成時に実行される処理)によって、インスタンス変数が初期化されます。なお、作成されたインスタンスはそれぞれ別々のものとして認識されるので、インスタンス変数の値はインスタンス毎に異なります。そのため、オブジェクト(クラスのインスタンス)毎に異なる情報を扱いたい場合に使用します。
3.クラス変数とは
staticキーワードを付けて宣言される変数であり、すべてのインスタンスで共有される共通の情報となります。あるオブジェクトからクラス変数の値を変更すると、その他のすべてのオブジェクトに影響が及びます。そのため、オブジェクト全体に共通する情報を扱いたい場合に使用します。
追記(2020/1/1) @shiracamus さんのコメントより
クラス変数はクラス間で継承関係がある場合、継承しているクラス毎に同じ名前で持つことができ、また、継承しているクラスをすべて辿り、最初に辿り着いた値を利用します。そのため、クラス変数は同じ名前であっても参照元のクラスによって値が異なる可能性があります。
(こちらの具体例を5.に追加)
4.それぞれの特徴
インスタンス変数 | クラス変数 | |
---|---|---|
特徴 | 作成されたオブジェクトそれぞれに対してインスタンス変数領域が確保される。そのため、オブジェクト毎に値が異なる。 | 1つのクラスに対して1つだけ作成され、すべてのオブジェクトに対して共通の値が使用される |
生存期間 | オブジェクトが作成されてから消滅するまで | プログラム開始から終了まで |
呼び出し方 | オブジェクトを代入した変数.インスタンス変数 | 1.クラス名.クラス変数 2.オブジェクトを代入した変数.インスタンス変数 |
宣言 | アクセス修飾子 型 変数名 | アクセス修飾子 staticキーワード 型 変数名 |
変更時の影響範囲 | インスタンス変数に紐づくオブジェクトだけ | すべてのオブジェクト |
5.具体例
インスタンス変数
public class Main {
public static void main(String[] args) {
Sample sampleA = new Sample();
Sample sampleB = new Sample();
sampleA.a = 10;
sampleB.a = 20;
System.out.println(sampleA.a);
System.out.println(sampleB.a);
}
}
public class Sample {
public int a;
}
10
20
それぞれのオブジェクトのインスタンス変数に異なる値を設定したので、
結果として、それぞれ異なる値が出力されます。
クラス変数
public class Main {
public static void main(String[] args) {
Sample sampleA = new Sample();
Sample sampleB = new Sample();
sampleA.setNum(30);
sampleB.setNum(40);
System.out.println(sampleA.getNum());
System.out.println(sampleB.getNum());
}
}
public class Sample {
public static int b;
public void setNum(int value) {
b = value;
}
public int getNum() {
return b;
}
}
40
40
クラス変数ではすべてのインスタンスで共通の値を共有し、かつ
ひとつのオブジェクトに対する変更がその他のオブジェクトに影響するので、
結果として最後に設定した40
がクラス変数の値として出力されます。
おまけ
public class Main {
public static void main(String[] args) {
var s1 = new Sample();
var s2 = new Sample();
System.out.println("Base: " + Base.a + ", " + Base.b);
System.out.println("Sample: " + Sample.a + ", " + Sample.b);
System.out.println("s1: " + s1.a + ", " + s1.b);
System.out.println("s2: " + s2.a + ", " + s2.b);
Base.a = 10;
Sample.a = 20;
s1.a = 30;
s2.a = 40;
System.out.println("Base: " + Base.a + ", " + Base.b);
System.out.println("Sample: " + Sample.a + ", " + Sample.b);
System.out.println("s1: " + s1.a + ", " + s1.b);
System.out.println("s2: " + s2.a + ", " + s2.b);
Base.b = 100;
Sample.b = 999;
System.out.println("Base: " + Base.a + ", " + Base.b);
System.out.println("Sample: " + Sample.a + ", " + Sample.b);
System.out.println("s1: " + s1.a + ", " + s1.b);
System.out.println("s2: " + s2.a + ", " + s2.b);
}
}
class Base {
static int a = 0;
static int b = 1;
}
class Sample extends Base {
static int b = 2;
}
Base: 0, 1
Sample: 0, 2
s1: 0, 2
s2: 0, 2
Base: 40, 1
Sample: 40, 2
s1: 40, 2
s2: 40, 2
Base: 40, 100
Sample: 40, 999
s1: 40, 999
s2: 40, 999
参考記事
SOFTWARE ENGINEERING
[tutorialspoint]
(https://www.tutorialspoint.com/What-is-the-difference-between-class-variables-and-instance-variables-in-Java)