twilight1730の資料室(wiki別館)
Java雑記002(static修飾子に関するあれこれ)
最終更新:
twilight1730
-
view
目次
static修飾子とは?
Javaでコードを書く上で時々使うstatic修飾子。意味は静的なという意味ですが、何が動的で何が静的なのでしょう。次のプログラムを見てください。
- Main.java
public class Main{
public static void main(String[] args){
//変数st1にStaticTestクラスのインスタンスを作成
System.out.println(">StaticTest st1 = new StaticTest();");
StaticTest st1 = new StaticTest();
st1.showValue("st1");
System.out.println("");
//st1のインクリメントメソッドを実行
System.out.println(">st1.increment();");
st1.increment();
st1.showValue("st1");
System.out.println("");
//変数st2にStaticTestクラスのインスタンスを作成
System.out.println(">StaticTest st2 = new StaticTest();");
StaticTest st2 = new StaticTest();
st1.showValue("st1");
st2.showValue("st2");
System.out.println("");
//st1のインクリメントメソッドを実行
System.out.println(">st1.increment();");
st1.increment();
st1.showValue("st1");
st2.showValue("st2");
System.out.println("");
//st2のインクリメントメソッドを実行
System.out.println(">st2.increment();");
st2.increment();
st1.showValue("st1");
st2.showValue("st2");
System.out.println("");
}
}
class StaticTest{
int i;
static int j;
//コンストラクタ
StaticTest(){
i=0; //メンバ変数iを初期化(staticなし)
j=0; //メンバ変数jを初期化(staticあり)
}
//iとjを加算するメソッド
public void increment(){
i++; //メンバ変数iをインクリメント(staticなし)
j++; //メンバ変数jをインクリメント(staticあり)
}
//iとjを表示するメソッド(場所を区別するために頭に番号)
public void showValue(String s){
System.out.println(s + ".i = " + i + "; "+ s +".j = " + j);
}
} - 実行内容
C:\Java\Jakki02>java Main
StaticTest st1 = new StaticTest();
st1.i = 0; st1.j = 0;
st1.increment();
st1.i = 1; st1.j = 1;
StaticTest st2 = new StaticTest();
st1.i = 1; st1.j = 0; コンストラクタによりjが初期化
st2.i = 0; st2.j = 0;
st2.i = 0; st2.j = 0;
st1.increment();
st1.i = 2; st1.j = 1;
st2.i = 0; st2.j = 1; st1のメソッドでst2のjも加算される
st2.i = 0; st2.j = 1; st1のメソッドでst2のjも加算される
st2.increment();
st1.i = 2; st1.j = 2; st2のメソッドでst1のjも加算される
st2.i = 1; st2.j = 2;
st2.i = 1; st2.j = 2;
new演算子によりStaticTestクラスのコンストラクタが呼び出され、それぞれインスタンスへの参照がst1とst2にそれぞれ保存されます。通常static宣言のない変数(ここではi)はインスタンスごと固有のメンバ変数でインスタンスフィールドと呼ばれます。
一方、static宣言により定義されたjはst1とst2で共有されています。static宣言をつけることにより変数はインスタンスごとに作成されるのではなく、そのクラスに唯一つ存在するメンバ変数になります。これをクラスフィールドと呼びます。
<まとめ>
- static宣言なし:インスタンスフィールド(インスタンス毎別々に保存される)
- static宣言あり:クラスフィールド(クラス毎に唯一つ存在する)
フィールドの初期化
先ほどはコンストラクタにて初期化を行いましたがそれではクラスフィールドはコンストラクタが呼び出されるたびに初期化されてしまいます。そこで暮らすフィールドの初期化の方法について考えます。
1.宣言時に初期化してみる
public class Main{
public static void main(String[] args){
StaticTest st1 = new StaticTest();
st1.increment();
StaticTest st2 = new StaticTest();
st2.increment();
StaticTest st3 = new StaticTest();
st3.increment();
}
}
class StaticTest{
int i = 0;
static int j = 0;
StaticTest(){
showValue();
}
public void increment(){
i++;
j++;
showValue();
}
public void showValue(){
System.out.println("i = " + i + "; j = " + j + ";");
}
}
i = 0; j = 0;
i = 1; j = 1;
i = 0; j = 1;
i = 1; j = 2;
i = 0; j = 2;
i = 0; j = 3;
i = 1; j = 1;
i = 0; j = 1;
i = 1; j = 2;
i = 0; j = 2;
i = 0; j = 3;