Java static修飾子

staticとは?

staticはクラスの構成要素に付けることができる修飾子で、メソッドとフィールドに付けることができます。付けられたフィールドおよびメソッドは、プログラムの実行時にメモリ割り当てを受け、プログラムが終了するまで消えずに保持されます。そして、その値はすべてのインスタンスで共有されます。

staticフィールド

通常のフィールドはインスタンスが生成されるたびに新しく生成され、さまざまな値を持ちます。しかし、staticが宣言されたフィールドはプログラムの実行時に生成され、すべてのインスタンスで共有されます。

まず、次のようなStudentクラスがあるとします。

Student.java

package com.devkuma.basic.statickeyword.ex1;

public class Student {
    static int number = 100;
    String name;

    Student(String name) {
        this.name = name;
    }
}

このStudentクラスでは、number変数がstaticとして宣言されています。

StudentSample1.java

package com.devkuma.basic.statickeyword.ex1;

public class StudentSample {

    public static void main(String[] args) {
        Student devkuma = new Student("devkuma");
        Student araikuma = new Student("araikuma");
        Student kimkc = new Student("kimkc");

        System.out.println(++devkuma.number);
        System.out.println(++araikuma.number);
        System.out.println(++kimkc.number);
    }
}

実行結果:

101
102
103

上の例では、Studentクラスのインスタンスを生成し、各インスタンスのnumber値を出力しています。

各インスタンスはそれぞれ101、102、103を出力しました。これは、すべてのインスタンスがstaticフィールドであるnumberを共有しているためです。つまり、下の図のように3つのインスタンスが1つのフィールドを参照しているのです。

static変数の共有

staticフィールドはインスタンスとは異なるタイミングで生成されるため、次のようにインスタンスではなくクラス名で参照できます。

package com.devkuma.basic.statickeyword.ex1;

public class StudentSample {

    public static void main(String[] args) {
        Student devkuma = new Student("devkuma");
        Student araikuma = new Student("araikuma");
        Student kimkc = new Student("kimkc");

        System.out.println(++devkuma.number);
        System.out.println(++araikuma.number);
        System.out.println(++kimkc.number);

        System.out.println(Student.number);
    }
}

実行結果:

101
102
103
103

staticメソッド

staticはクラスの構成要素に宣言されるため、メソッドにもstaticを宣言できます。

このようなメソッドをstaticメソッドと呼びます。staticメソッドでは、staticフィールドとローカル変数だけを使用できます。

Student.java

package com.devkuma.basic.statickeyword.ex2;

public class Student {
    static int number = 100;
    String name;

    Student(String name) {
        this.name = name;
    }

    public static void printNumber() {
        System.out.println("지금 Student의 number는" + number + "입니다.");
    }
}

StudentSample.java

package com.devkuma.basic.statickeyword.ex2;

public class StudentSample {

    public static void main(String[] args) {
        Student.printNumber();
        Student.number++;
        Student.printNumber();
    }
}

実行結果:

지금 Student의 number는 100입니다.
지금 Student의 number는 101입니다.

上の例のように、インスタンスを生成しなくてもクラス名を参照して呼び出すことができます。

staticメソッドで使用できる変数

package com.devkuma.basic.statickeyword.ex2;

public class Student {
    static int number = 100;
    String name;

    Student(String name) {
        this.name = name;
    }

    public static void printNumber() {
        int localVariable = 100; // ok
        name = "a"; // error
        System.out.println("지금 Student의 number는 " + number + "입니다.");
    }
}

上の例では、ローカル変数localVariableの宣言時にはエラーが発生しませんが、クラスメンバー変数nameではエラーが発生しています。

staticは前述のように、ローカル変数とstaticフィールドだけを使用できます。staticメソッドはインスタンスを生成しなくても使用できるメソッドです。そのため、通常のフィールドはインスタンスが生成されるときに作られるので、staticメソッドでは使用できません。