static 변수

한라봉봉·2023년 12월 16일

JAVA

목록 보기
9/16

static 키워드는 주로 멤버 변수와 메서드에 사용된다.

멤버 변수에 static 키워드가 왜 필요한가

-> 특정 클래스를 통해 생성된 객체의 수를 세는 프로그램으로 알아보자.

1. Data1 인스턴스만 생성시

아래 코드는 의도대로 동작하지 않는다.
객체를 생성할 때마다 Data1의 인스턴스는 새로 만들어진다. 인스턴스에 포함된 count 변수도 새로 만들어지기 때문이다.
인스턴스에 사용되는 멤버변수 count 값은 인스턴스끼리 공유되지 않는다.

public class Data1 {
    public String name;
    public int count;

    public Data1(String name) {
        this.name = name;
        count++;
    }
}

main

    public static void main(String[] args) {
        Data1 data1 = new Data1("A");
        System.out.println("A count=" + data1.count);

        Data1 data2 = new Data1("B");
        System.out.println("B count=" + data2.count);

        Data1 data3 = new Data1("C");
        System.out.println("C count=" + data3.count);
    }

2. count 클래스 추가하여 해당 클래스 인스턴스 공유

동일한 Counter 인스턴스의 count값을 증가시키면 값이 누적된다.
그런데 여기엔 불편한 점들이 있다.
1) Data2 클래스 관련 일인데, Counter 별도 클래스를 추가로 사용해야 한다.
2) Data2 생성자의 매개변수도 추가되고, 생성자가 복잡해진다. 호출 부분도 복잡해진다.

public class Counter {
    public int count;
}
public class Data2 {
    public String name;

    public Data2(String name, Counter counter) {
        this.name = name;
        counter.count++;
    }
}

main

    public static void main(String[] args) {
        Counter counter = new Counter();
        Data2 data1 = new Data2("A", counter);
        System.out.println("A count=" + counter.count);

        Data2 data2 = new Data2("B", counter);
        System.out.println("B count=" + counter.count);

        Data2 data3 = new Data2("C", counter);
        System.out.println("C count=" + counter.count);
    }

3. static 변수 사용하여 공용 사용 변수 만들기

1) count를 static변수로 선언하였다. 이렇게 클래스 멤버변수에 static 키워드를 붙이게 되면 static 변수, 정적 변수 또는 클래스 변수라 한다. 객체가 생성되면 정적변수 count의 값을 하나 증가시켜 의도한 바대로 코드작성이 가능하다!

public class Data3 {
    public String name;
    public static int count; //static

    public Data3(String name) {
        this.name = name;
        count++;
    }
}

main

    public static void main(String[] args) {
        Data3 data1 = new Data3("A");
        System.out.println("A count=" + Data3.count);

        Data3 data2 = new Data3("B");
        System.out.println("B count=" + Data3.count);

        Data3 data3 = new Data3("C");
        System.out.println("C count=" + Data3.count);

        //추가
        //인스턴스를 통한 접근
        Data3 data4 = new Data3("D");
        System.out.println(data4.count);

        //클래스를 통한 접근
        System.out.println(Data3.count);
    }

2) 정적 변수에 접근하는 방법: main()을 보면 Data3.count와 같이 클래스에 직접 접근하는 것같이 보인다. 클래스명.변수명 으로 접근하면 된다.
3) static이 붙은 멤버 변수는 메서드 영역에서 관리한다.
-> static이 붙은 멤버 변수 count는 인스턴스 영역에 생성되지 않는다.
4) Data3("A") 인스턴스를 생성하면 생성자가 호출된다.
5) 생성자에는 count++ 코드가 있다. count는 static이 붙은 정적 변수다. 인스턴스 영역이 아닌 메서드 영역에서 관리한다. 따라서 이경우 메서드 영역에 있는 count의 값이 하나 증가된다.(붕어빵 틀 자체를 바꾸는것과 같다)
6) 참고로, count++의 경우 Data3.count++과 같이 정적 변수에 접근 규칙으로 표기하는 것이 맞으나 자기자신(Data3) 클래스 내에서는 생략 가능하다.

static 변수 정리

1. 멤버변수(필드)의 종류

  1. 인스턴스 변수: static이 붙지 않은 변수
    1) static이 붙지 않은 멤버 변수는 인스턴스를 생성해야 사용할 수있고, 인스턴스에 소속되어있다. 따라서 인스턴스 변수라 한다.
    2) 인스턴스 변수는 인스턴스를 만들때마다 새로 만들어진다.
  2. 클래스 변수: static이 붙은 멤버 변수
    1) 클래스변수, 정적 변수, static 변수 등으로 부른다. 용어를 모두사용하니 주의
    2) static이 붙은 멤버 변수는 인스턴스와 무관하게 클래스에 바로 접근해서 사용할 수 있고, 클래스 자체에 소속되어있다. 따라서 클래스 변수라 한다.
    3) 클래스 변수는 자바 프로그램을 시작할 때 딱 1개가 만들어진다. 인스턴스와는 다르게 보통 여러곳에서 공유하는 목적으로 사용된다.

2. 변수와 생명주기

  1. 지역 변수: 지역 변수는 스택 영역에 있는 스택 프레임 안에 보관. 메서드가 종료되면 스택프레임도 제거되는데, 이때 해당 스택 프레임에 포함된 지역변수도 함께 제거된다. 지역변수는 생존주기가 짧다.
  2. 인스턴스 변수: 인스턴스에 있는 멤버변수를 인스턴스 변수라 한다. 인스턴스 변수는 힙 영역을 사용한다. 힙 영역은 GC가 발생하기 전까지는 생존하기 때문에 보통 지역 변수보다 생존 주기가 길다
  3. 클래스 변수: 클래스 변수는 메서드 영역의 static 영역에 보관되는 변수이다. 메서드 영역은 프로그램 전체에서 사용하는 공용 공간이다. 클래스 변수는 해당 클래스가 JVM에 로딩 되는 순간 생성된다. 그리고 JVM이 종료될 때까지 생명 주기가 이어진다. 따라서 가장 긴 생명주기를 가진다.

3. 접근

  1. 인스턴스를 통한 접근
    정적 변수의 경우 인스턴스를 통한 접근은 추천하지 않는다. 코드를 읽을때 마치 인스턴스 변수에 접근하는 것처럼 오해할 수있기 때문이다.
    인스턴스를 통해 접근시에도 결국 메서드 영역에 있는 변수에 동일하게 접근한다.
  2. 클래스를 통한 접근
    정적 변수는 클래스에서 공용으로 관리하기 때문에 클래스를 통해서 접근하는것이 더 명확하다. 따라서 정적 변수에 접근할 때는 클래스를 통해서 접근하자.
profile
백엔드 개발공부 로그를 기록합니다

0개의 댓글