자바 필드 구분 클래스 변수·인스턴스 변수·지역 변수
자바 필드 구분(클래스 변수, 인스턴스 변수, 지역 변수)은 메모리 구조와 수명 주기를 이해하는 첫걸음입니다. 올바르게 구분·사용하면 메모리 효율을 높이고 버그를 예방할 수 있습니다.
클래스 변수 static – 모든 인스턴스가 공유하는 데이터
특징
static키워드로 선언 → 클래스 로드 시 메서드 영역에 1회 생성- 인스턴스를 만들지 않고 클래스명.필드 로 접근
- 프로그램 종료까지 유지되어 전역 상태 관리에 유용
class Config {
static int MAX_USER = 100; // 클래스 변수
}
System.out.println(Config.MAX_USER);
사용 팁
- 상수는
public static final로 선언하고 대문자 스네이크(MAX_USER) 사용 - 다중 스레드 환경에서는 동기화(e.g.,
AtomicInteger) 고려
인스턴스 변수 – 객체마다 고유한 상태
특징
static키워드 없음- 힙(Heap) 영역에 저장되고 가비지 컬렉터가 관리
- 각 객체가 독립 값 보유 → 한 인스턴스 변경이 다른 인스턴스에 영향 없음
class User {
String name; // 인스턴스 변수
}
User u1 = new User();
User u2 = new User();
u1.name = "Alice";
u2.name = "Bob"; // u1.name은 그대로 "Alice"
사용 팁
- 필드는 기본적으로
*private**으로 숨기고 Getter/Setter로 캡슐화 - 불변 객체(Immutable)가 필요하면
final+ Setter 제거
지역 변수 – 메서드·블록 내부의 일시적 값
특징
- 스택(Stack) 에 저장 → 블록 종료 시 즉시 소멸
- 명시적 초기화 필수 (컴파일러가 기본값 부여 X)
public/private/static과 같은 접근 제어 불가 (메서드 로컬 영역)
void doWork() {
int counter = 0; // 지역 변수
System.out.println(counter);
}
사용 팁
- 블록 범위를 최소화해 메모리 사용과 사이드이펙트 감소
- 람다/익명 클래스에서 사용 시 effectively final 요건을 충족해야 함
필드 구분 비교표
| 구분 | 키워드 | 메모리 위치 | 생성 시점 | 소멸 시점 | 기본 초기화 |
|---|---|---|---|---|---|
| 클래스 변수 | static |
메서드 영역 | 클래스 로드 | JVM 종료 | 자동 |
| 인스턴스 변수 | (없음) | 힙 | 객체 생성 | 객체 소멸 | 자동 |
| 지역 변수 | (없음) | 스택 | 블록 진입 | 블록 종료 | 필수 수동 초기화 |
필드 활용 베스트 프랙티스
- 상수 →
public static final - 공통 설정 →
private static+ Getter - 객체 상태 →
private인스턴스 변수 - 계산용 임시 값·루프 인덱스 → 지역 변수
질문 정리
Q1. 클래스 변수는 왜 가끔 final과 함께 쓰나요?
→ 값이 변하지 않는 전역 상수로 보장하기 위해 static final 조합을 사용합니다.
Q2. 지역 변수를 초기화하지 않으면 어떤 오류가 나나요?
→ 컴파일 단계에서 “variable might not have been initialized” 에러가 발생합니다.
Q3. 인스턴스 변수는 스레드마다 별도 메모리를 가지나요?
→ 아닙니다. 인스턴스가 동일하면 스레드와 무관하게 값을 공유합니다. 필요하다면 ThreadLocal을 사용하세요.
Q4. 왜 static 필드에 this를 사용할 수 없나요?
→ static은 클래스 레벨이라 인스턴스 참조(this)가 존재하지 않기 때문입니다.
Q5. 가비지 컬렉션이 클래스 변수를 회수할 때도 있나요?
→ 클래스 언로딩 시점에 함께 회수될 수 있지만, 일반적으로 JVM 종료까지 유지된다고 보는 것이 안전합니다.
댓글남기기