本記事の目次
static変数とは・staticメソッドとは
ご存じのとおり、クラスには属性を表す変数と、操作を表すメソッドを定義します。このクラスに用意した変数やメソッドを総称してメンバと呼びます(図1)。
メンバ変数は、そのクラスが持つべき属性を表現するために使用します。メンバ変数には、表1に挙げたインスタンス変数とstatic変数の2種類があります。
メンバ変数 | メンバメソッド | |
---|---|---|
インスタンスメンバ |
インスタンス変数 (非static変数) |
インスタンスメソッド (非staticメソッド) |
staticメンバ | static変数 | staticメソッド |
変数を宣言するときにstatic修飾子を指定することで、static変数として扱われます。メソッドも同様に、static修飾子を指定することでstaticメソッドとして扱われます。なお、static変数はクラス変数、staticメソッドはクラスメソッドとも呼ばれ、クラスに対して静的(static)に存在するメンバであることを意味します。
サンプルSample1.javaで、インスタンスメンバとstaticメンバの定義を確認しましょう。
class Sample1 { int instanceVal = 100; static int staticVal = 200; void methodA() { System.out.println("methodA(): " + instanceVal); } static void methodB() { System.out.println("methodB(): " + staticVal); } }
instanceVal
はインスタンス変数、staticVal
はstatic変数です。また、methodA()
は非static(インスタンス)メソッド、methodB()
はstaticメソッドです。定義の違いはstatic修飾子の有無だけです。では、static修飾子の有無により何が違うのでしょうか。
違うのはメモリの確保場所です。static修飾子のないインスタンスメンバには、クラスのインスタンス(オブジェクト)ごとに領域が確保されます。例えば、1つのクラスから3つのインスタンスを生成すれば、「3つ×インスタンスメンバの数」だけ領域が確保されます。領域が確保されるタイミングは、インスタンス化を行ったときです。
一方、staticメンバはクラス単位で領域が確保されます。そのため、staticメンバに確保される領域は、たとえ複数のインスタンスが生成されても、1つだけです。領域が確保されるのは、クラスをメモリ上に読み込んだときです。
static変数とstaticメソッドの呼び出し
インスタンスメンバ(変数・メソッド)を呼び出す場合、インスタンス(オブジェクト)を参照する変数を使って、「参照変数名.インスタンス変数名
」や「参照変数名.インスタンスメソッド名()
」と記述しますよね。これは、インスタンスメンバがインスタンス(オブジェクト)ごとに領域が確保されるためです。
一方、staticメンバ(変数/メソッド)はクラスごとに確保される領域なので、「クラス名.static変数名
」や「クラス名.staticメソッド名()
」と記述します。また、インスタンス化しなくても呼び出しができます。staticメンバは、クラスが読み込まれた時点でメモリ上に展開されているためです。
次に示すサンプルSample2.javaは、先ほど作成したSample1
クラスの各変数、メソッドを呼び出しています。Sample1.javaのコードと照らしながら確認してみましょう。
class Sample2 { public static void main(String[] args) { //System.out.println(Sample1.instanceVal); //① NG System.out.println(Sample1.staticVal); //② OK //Sample1.methodA(); //③ NG Sample1.methodB(); //④ OK Sample1 obj = new Sample1(); System.out.println(obj.instanceVal); //⑤ OK System.out.println(obj.staticVal); //⑥ OK obj.methodA(); //⑦ OK obj.methodB(); //⑧ OK } }
200 methodB(): 200 100 200 methodA(): 100 methodB(): 200
インスタンスメンバは、インスタンス化しなければ呼び出せません。したがって、①と③はコメントを外すとコンパイルエラーとなります。また、通常、staticメンバはクラス名.メンバ名
で呼び出しますが、⑥や⑧と記述しても実行可能です。