1. 클래스 변수(Class variable) vs 인스턴스 변수(Instance variable)

멤버 변수  static이 붙은 것은 클래스 변수, 붙지 않은 것은인스턴스 변수이다.

클래스 변수(Static 멤버)

  • 클래스 내에 Static 키워드로 선언된 변수
  • 처음 JVM이 실행되어 클래스가 메모리에 올라갈 때 ~ 프로그램이 종료될 때까지 유지
  • 클래스가 여러 번 생성되어도 Static 변수는 처음 딱 한 번만 생성됨
  • 동일한 클래스의 모든 객체들에 의해서 공유됨

인스턴스 변수(Non-static 멤버)

  • 클래스 내에 선언된 변수
  • 객체 생성 시마다 매번 새로운 변수가 생성됨
  • 클래스 변수와 달리 공유되지 않음

지역변수

  • 메소드 블럭 안에 선언된 변수로 메소드 호출 시점 ~ 메소드 종료 시점 동안 유지된다.
변수의 종류 선언 위치 생성 시기
클래스 변수(class variable) 클래스 영역 클래스가 메모리에 올라갈 때
인스턴스 변수(instance variable) 인스턴스가 생성되었을 때
지역 변수(local variable) 클래스 영역 이외의 영역(메서드, 생성자, 초기화 블럭 내부) 변수 선언문이 수행되었을 때

 

아래 예제에서 클래스 변수 classVar는 처음 한 번만 생성되고 동일한 객체를 staticTest1과 staticTest2에서 서로 공유하기 때문에 둘 다 바뀌지만, instanceVar는 객체 생성 시 마다 매번 새로 메모리에 할당되기 때문에 staticTest1.instanceVar만 변경된다.

public static class StaticTest {
    static int classVar = 10; //클래스 변수
    int instatnceVar = 28; //인스턴스 변수
    
    public void method() {
        int localVar = -100; //지역변수(메소드 블럭 내에서만 사용 가능)
        System.out.println(localVar);
    }
}

public static void main(String[] args){
    StaticTest staticTest1 = new StaticTest();
    StaticTest staticTest2 = new StaticTest();

    System.out.println("1. " + staticTest1.classVar + ", " + staticTest1.instanceVar);
    System.out.println("2. " + staticTest2.classVar + ", " + staticTest2.instanceVar);

    staticTest1.classVar = 12;
    staticTest1.instanceVar = 400;

    System.out.println();
    System.out.println("1. " + staticTest1.classVar + ", " + staticTest1.instanceVar);
    System.out.println("2. " + staticTest2.classVar + ", " + staticTest2.instanceVar);

}
// 출력 결과 
1. 10, 28 
2. 10, 28 

1. 12, 400 
2. 12, 28

2. 클래스 변수, 인스턴스 변수, 지역 변수가 메모리에 적재되는 위치

 

메소드 영역

  • 클래스에 대한 정보와 함께 클래스 변수(static variable)가 저장되는 영역.
  • JVM은 자바 프로그램에서 특정 클래스가 사용되면 해당 클래스의 클래스 파일(*.class)을 읽어들여, 클래스에 대한 정보를 메소드 영역에 저장한다.

힙 영역

  • 모든 인스턴스 변수(멤버 변수)가 저장되는 영역.
  • new 키워드를 사용해 인스턴스가 생성되면, 해당 인스턴스의 정보를 힙 영역에 저장한다.
  • 힙 영역은 메모리의 낮은 주소 -> 높은 주소의 방향으로 할당된다.

스택 영역

  • 메소드가 호출될 때, 메소드의 스택 프레임이 저장되는 영역.
  • 메소드 호출 시, 메소드 호출과 관계되는 매개변수와 지역 변수를 스택 영역에 저장한다.
  • 스택 영역은 메소드의 호출과 함께 할당되며, 메소드의 호출이 완료되면 소멸한다.
  • 스택 영역에 저장되는 메소드의 호출 정보를 스택 프레임이라고 부른다.
  • 후입 선출의 구조를 갖고 있으며, 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.

 

3. 클래스 변수(Static)의 주의점, 클래스 변수가 필요한 이유 

주의
  • 실제 static 멤버의 생성 시점은 JVM에 따라 다르다.
  • 보통 JVM은 필요한 대부분의 클래스를 처음부터 로딩하기 때문에 static멤버의 생성 시점은 JVM이 시작되는 시점이라고 할 수 있다.
  • 제약조건
    • static 메소드는 오직 static멤버만 접근 가능
    • => static메소드도 static멤버와 로드되는 시점이 동일하기 때문에 객체가 생성되지 않은 상황에서도 변수를 사용할 수 있어야 한다.
    • this 키워드 사용 불가
    • => this는 호출 당시 실행 중인 객체를 가리키는 레퍼런스인데 static메소드는 객체가 생성되지 않은 상황에서도 호출이 가능하기 때문이다.

 

클래스 변수가 필요한 이유
  • 자바에서는 캡슐화 원칙에 따라서 C/C++과 달리 어떤 변수나 함수도 클래스 바깥에 존재할 수 없다. 따라서 전역변수나 전역메소드로 사용해야 할 경우 static을 이용해서 해결한다.

 

 

 

참고 

- https://sujinhope.github.io/2021/03/03/Java-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%B3%80%EC%88%98,-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EB%B3%80%EC%88%98-%EC%B0%A8%EC%9D%B4(Static%EB%B3%80%EC%88%98%EC%99%80-Non-Static%EB%B3%80%EC%88%98).html

- http://www.tcpschool.com/java/java_array_memory

반응형

BELATED ARTICLES

more