정적 변수(static)와 동적 할당

소만이·5일 전

JAVA

목록 보기
5/5

[Java] 정적 변수(static)와 동적 할당 정리

들어가며

C를 공부하다 보면 정적 변수와 동적 변수라는 말을 자주 접합니다. 그런데 자바에서는 "동적 변수"라는 공식 용어가 따로 없어서 헷갈리기 쉽습니다. 이 글에서는 자바에서 변수가 어떻게 나뉘는지, 정적 변수는 무엇이고 C의 동적 할당에 해당하는 개념은 무엇인지 정리합니다.

1. 자바의 변수 종류

자바는 변수를 선언 위치와 static 키워드 유무로 구분합니다.

public class Example {
    static int classVar = 0;   // 정적 변수 (클래스 변수)
    int instanceVar = 0;       // 인스턴스 변수
 
    void method() {
        int localVar = 0;      // 지역 변수
    }
}
종류선언 위치생성 시점소멸 시점저장 영역
정적 변수 (static)클래스 안, static 있음클래스 로드 시프로그램 종료 시메서드 영역
인스턴스 변수클래스 안, static 없음new로 객체 생성 시객체가 GC될 때힙
지역 변수메서드 안메서드 호출 시메서드 종료 시스택

정적 변수의 정확한 저장 위치는 JVM 버전과 구현에 따라 조금씩 다릅니다. 여기서는 개념적으로 "클래스 단위로 관리되는 영역"이라고 이해하면 충분합니다.

2. 정적 변수 (static 변수)

정적 변수는 클래스에 하나만 존재하며, 모든 객체가 공유하는 변수입니다.

class Counter {
    static int total = 0;  // 모든 객체가 공유
    int mine = 0;          // 객체마다 따로 존재
 
    Counter() {
        total++;
        mine++;
    }
}
 
public class Main {
    public static void main(String[] args) {
        Counter a = new Counter();
        Counter b = new Counter();
        Counter c = new Counter();
 
        System.out.println(Counter.total);  // 3
        System.out.println(a.mine);         // 1
        System.out.println(c.mine);         // 1
    }
}
  • total은 객체를 몇 개 만들든 하나뿐입니다.
  • mine은 객체마다 별도로 생성됩니다.
  • 객체 없이 클래스 이름으로 바로 접근할 수 있습니다. (Counter.total)

정적 변수를 쓰기 좋은 경우

public static final double PI = 3.14159;   // 상수
static int nextId = 1;                     // 객체 간 공유되는 카운터
  • 변하지 않는 상수 (static final)
  • 모든 객체가 공유해야 하는 값 (생성 개수, ID 발급 등)
  • 유틸리티성 값이나 설정값

3. 자바에서 "동적"에 해당하는 것: new

C에서 malloc으로 실행 중에 메모리를 할당하는 것과 가장 비슷한 것이 자바의 new로 객체를 생성하는 것입니다. 이렇게 만든 객체는 힙(Heap)에 생기고, 크기를 실행 중에 정할 수 있습니다.

Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
 
int[] arr = new int[n];   // 실행 중에 크기 결정
ArrayList<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);   // 크기가 자동으로 늘어남

해제는 가비지 컬렉터(GC)가 담당

C와 결정적으로 다른 점은 free가 없다는 것입니다. 더 이상 참조되지 않는 객체는 GC가 알아서 회수합니다.

void test() {
    int[] arr = new int[1000000];
    // free 필요 없음
    // 메서드가 끝나 참조가 사라지면 GC가 정리
}

4. C와 자바 비교

C자바
정적 변수static, 전역 변수static 필드
동적 할당malloc / freenew (해제는 GC가 자동)
메모리 누수free 안 하면 발생거의 없음 (참조를 계속 들고 있으면 발생 가능)
포인터직접 사용없음 (참조 변수만 존재)

5. static 사용 시 주의점

(1) static 메서드에서는 인스턴스 변수에 직접 접근할 수 없다

class Example {
    int x = 10;
    static int y = 20;
 
    static void staticMethod() {
        System.out.println(y);     // OK
        // System.out.println(x);  // 컴파일 오류
    }
}

static 메서드는 객체 없이 호출되기 때문에, 특정 객체에 속한 인스턴스 변수가 존재하는지 보장할 수 없습니다.

(2) 값이 공유되므로 예상치 못한 변경에 주의

static 변수는 모든 객체와 스레드가 공유합니다. 어디서든 값이 바뀔 수 있어 디버깅이 어렵고, 멀티스레드 환경에서는 동기화 문제가 생길 수 있습니다. 상수(static final)나 꼭 필요한 공유 값이 아니라면 남용하지 않는 것이 좋습니다.

(3) static 변수는 오래 살아남는다

프로그램이 끝날 때까지 메모리에 남기 때문에, static 컬렉션에 계속 데이터를 쌓으면 GC가 회수하지 못해 메모리 누수의 원인이 될 수 있습니다.

마무리

  • 자바에는 정적 변수(static)가 있으며, 클래스 단위로 하나만 존재하고 모든 객체가 공유합니다.
  • "동적 변수"라는 공식 용어는 없고, new로 힙에 객체를 생성하는 것이 C의 동적 할당에 대응합니다. 해제는 GC가 담당합니다.
  • 실무에서는 정적/동적 구분보다 지역 변수 / 인스턴스 변수 / 클래스(static) 변수로 나누어 이해하는 것이 일반적입니다.

0개의 댓글