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 메서드에서는 사용할 수 없다.