본문 바로가기

프로그래밍언어/Java

[Java 기본] static 변수

static 변수


static은 주로 멤버 변수와 메서드에 사용한다.

 

package static1;

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

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

생성된 객체의 수를 세어야 한다. 객체가 생성될 때마다 생성자를 통해 인스턴스의 멤버변수인 count 값을 증가시킨다. 

 

public class DataCountMain1 {
    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 ="  +data1.count);

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

    }
}

 

실행 결과

 

=> 카운트는 증가하지 않는다. 객체를 생성할 때마다 Data 인스턴스와 count 변수가 새로 만들어지기 때문이다. 

 

인스턴스에 사용되는 멤버변수 count 는 인스턴스끼리 서로 공유되지 않는다. 이 문제를 해결하려면 변수를 서로 공유해야 한다. 

 

외부 인스턴스에 카운트 저장


Counter.java

package static1;

public class Counter {
    public int count;

}

 

Data2.java

package static1;

public class Data2 {
    public String name;

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

 

 

DataCountMain2.java

 

package static1;

public class DataCountMain2 {
    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);

    }
}

 

실행 결과

 

이번엔 값이 정상적으로 증가했다. Counter 인스턴스를 공용으로 사용하기 때문에 객체를 생성할 때 마다 값을 증가되는 것이다. 

 

그러나 여기에는 불편한 점들이 있다. 

Data2가 몇 개 생성됐는지를 구하기 위해서 무관한 Counter 클래스를 만들어야 한다. 

 

 

static 변수 사용


특정 클래스에서 공용으로 사용할 수 있는 변수를 만들면 편리할 것이다. static 키워드를 사용하면 공용으로 사용하는 변수를 만들 수 있다.

 

Data3.java

package static1;

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

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

 

멤버 변수에 static을 붙이게 되면 static 변수, 정적 변수 또는 클래스 변수라 한다. 

 

 

DataCountMain3.java

public class DataCountMain3 {
    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);

    }
}

 

 

=> 코드를 보면 count 정적 변수에 접근할 때 클래스 명에 .(dot)을 사용한다. 

 

  • static이 붙은 멤버 변수는 메서드 영역에서 관리한다. 
    • 인스턴스 영역에 생성되지 않는다. 대신에 메서드 영역에서 이 변수를 관리한다. 
  • Data3("A") 인스턴스를 생성하면 생성자가 호출된다. 생성자에는 count++ 코드가 있는데 여기서 count 변수는 정적 변수 이다. 정적변수는 메서드 영역에서 관리하기 때문에 메서드 영역에 있는 count 의 값이 증가하는 것이다. 

 

  • Data3("B")를 호출해도 마찬가지 이다. 

 

 

static이 붙은 정적 변수에 접근하려면 클래스명.변수명 으로 접근하면된다. 

 

멤버변수의 종류


인스턴스 변수 : static이 붙지 않은 멤버 변수.

  - 인스턴스를 생성해야 사용할 수 있고, 인스턴스에 소속되어 있다. 

  - 인스턴스를 만들 때마다 새로 생성된다. 

 

클래스 변수: static이 붙은 변수

  - 클래스 변수, 정적 변수, static 변수 등으로 부른다 .

  - 클래스에 바로 접근해서 사용할 수 있고, 클래스 자체에 소속되어 있다. 

  - 클래스 변수는 자바 프로그램을 시작할 때 1개가 만들어진다. 인스턴스와는 다르게 여러 곳에서 공유하는 목적으로 사용된다. 

 

변수와 생명주기


지역 변수(매개변수 포함) : 지역 변수는 스택 영역에 있는 스택 프레임 안에 보관된다. 메서드가 종료되면 스택프레임이 제거되면서 지역변수도 함께 제거된다.

인스턴스 변수: 인스턴스에 있는 멤버 변수를 인스턴스 변수라 한다. 힙 영역을 사용한다. 힙 영역은 GC가 발생하기 전까지는 생존하기 때문에 지역 변수보다 생존주기가 길다. 

클래스 변수 : 클래스 변수는 메서드 영역의 static 영역에 보관된다. 메서드 영역은 프로그램 전체에서 사용하는 공용 공간이다. 클래스 변수는 해당 클래스가 JVM에 로딩 되는 순간 생성된다. 그리고 JVM이 종료될 때 까지 생명주기가 이어진다 

 

힙 영역에 생성되는 인스턴스 변수는 동적으로 생성되고, 제거되는 반면 static 변수는 프로그램 실행 시점에 생성되고, 프로그램 종료와 함께 제거되므로 정적 변수라 한다. 

 

 

 

* 인프런 '김영한의 실전 자바 - 기본편'을 참고하여 작성하였습니다.