본문 바로가기

Java/Java

(JAVA) Static

Static은 왜 사용하는가?

생성 시점 : Static의 생성 시점은 프로그램이 로드되는 순간 static 영역(데이터 영역) 으로 메모리가 올라간다.

따라서 불변하는 클래스, 메서드, 변수는 static으로 사용하는 것이 효율적인다.

단, static이 너무 큰 메모리를 차지한다면 로드될 시에 성능 측면에서 큰 부하가 생기므로 작은 메모리 만을 할당해서 적절히 사용하는 것이 효율적이다.

static의 메모리 구조


예시

아래 코드는 serialNum이 static으로 선언되어 있으며 10000으로 초기화되어있다.

Student 인스턴스를 생성할 때마다 serialNum은 1씩 증감한다.

package me.choi.chapter02.pizza.generic.staticex;

public class Student {
    public static int serialNum = 10000;
    private int studentID;
    public String studentName;
    public String address;

    public Student(String studentName) {
        this.studentName = studentName;
        serialNum++;
        studentID = serialNum;

    }

    public Student(int studentID, String studentName) {
        this.studentID = studentID;
        this.studentName = studentName;
        serialNum++;
        studentID = serialNum;
    }

    public int getStudentID() {
        return studentID;
    }

    @Override
    public String toString() {
        return "Student{" +
                "studentName='" + studentName + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

}

studentChoi, studentLee라는 인스턴스를 생성하여 serialNum을 체크하면 1씩 증감되는 결과를 예상할 수 있다.

package me.choi.chapter02.pizza.generic.staticex;

public class StudentIDTest {
    public static void main(String[] args) {

        Student studentChoi = new Student("choi");
        System.out.println(Student.serialNum);
        Student studentLee = new Student("lee");
        System.out.println(Student.serialNum);

        System.out.println("학번 check");
        System.out.println(studentChoi.getStudentID());
        System.out.println(studentLee.getStudentID());



    }
}

이때 serialNum은 studentChoi, studentLee각각의 힙 메모리에 올라가는 것이 아니라 로드 시 생성되었던 스태틱 영역을 참조한다.

따라서 studentChoi,studentLee은 같은 serialNum을 참조하게 된다.


왜 studentChoi는 serialNum을 참조할 수 없을까?

위에 언급하였듯이 serialNum은 스태틱 영역에 올라감으로써 각각의 인스턴스가 생성되는 힙 메모리 영역에 생성되지 않았음을 보여준다.

static 변수 사용방법

static 변수를 사용하려면 위와 같이 클래스에서 직접 선언을 해야 한다.


static은 static으로 사용해야 한다.

public static int getSerialNum() {
        int i = 0;
        studentName = "Jun";

        return serialNum;
    }

위의 코드에서 틀린 점은 무엇일까?

1. int i는 static 메서드 내부에서 사용하는 지역변수 이기 때문에 문제없음.

2. serialNum 도 똑같은 static 변수 이기 때문에 상관없음.

단, studentName은 인스턴스 변수이기 때문에 사용할 수 없다.

studentName은 static 영역에 메모리가 올라간 이후의 작업이기 때문에 사용할 수 없다.

즉, new () 해서 인스턴스를 생성하고 나서 값을 생성할 수 있기 때문에 순서상 문제가 있다.

하지만 일반 메서드에서는 static 변수를 가공하여 사용할 수 있다. (프로그램이 로드될 때 이미 static은 메모리에 올라가 있기 때문에)