Java에서 변수는 크게 두 종류로 나뉩니다.
값 자체를 저장하는 기본 타입 변수와, 주소를 저장하는 참조변수입니다.
참조변수가 왜 반드시 주소를 가져야 하는지, 주소가 없으면 어떤 문제가 생기는지 정리해보겠습니다.
참조변수란?
참조변수는 객체가 저장된 힙 메모리의 주소를 담는 변수입니다.
클래스 타입, 배열, 인터페이스 타입으로 선언된 변수가 모두 참조변수입니다.
Member member = new Member("홍길동", 25);
// ↑ ↑
// 참조변수 힙에 생성된 객체
변수 member에는 객체 자체가 아닌, 힙 메모리의 주소값이 저장됩니다.
참조변수는 반드시 주소를 가져야 한다
참조변수는 주소를 통해 객체에 접근합니다.
주소가 없는 상태, 즉 null인 상태에서 객체에 접근하려 하면 NullPointerException이 발생합니다.
Member member = null; // 주소 없음
System.out.println(member.name); // NullPointerException 발생!
참조변수가 주소를 가지고 있어야만 그 주소를 따라가 객체에 접근할 수 있습니다.
메모리 구조로 이해하기
[주소가 있는 경우]
[스택] [힙]
┌──────────┐ ┌──────────────────┐
│ member │ │ Member 객체 │
│ 0x100 ───────▶ │ name = "홍길동" │
└──────────┘ │ age = 25 │
└──────────────────┘
→ 주소(0x100)를 통해 객체에 접근 가능
[주소가 없는 경우 - null]
[스택]
┌──────────┐
│ member │
│ null │ ──▶ 가리키는 곳 없음 → NullPointerException!
└──────────┘
코드로 확인하기
주소를 가진 참조변수
Member m1 = new Member("홍길동", 25); // 힙에 객체 생성, 주소 저장
Member m2 = new Member("김철수", 30); // 힙에 새 객체 생성, 다른 주소 저장
System.out.println(m1.name); // "홍길동" - 주소로 접근 성공
System.out.println(m2.name); // "김철수" - 주소로 접근 성공
System.out.println(m1 == m2); // false - 주소가 다름
주소를 공유하는 경우
Member m1 = new Member("홍길동", 25);
Member m2 = m1; // m1의 주소를 m2에 복사
System.out.println(m1 == m2); // true - 같은 주소
m2.name = "김철수";
System.out.println(m1.name); // "김철수" - m1도 영향받음
m2 = m1은 객체를 복사하는 게 아니라 주소를 복사하는 것입니다.
두 변수가 같은 객체를 가리키기 때문에 한쪽을 수정하면 양쪽 모두 바뀝니다.
null 상태에서 접근하면
Member member = null; // 주소 없음
if (member != null) { // null 체크 후 접근
System.out.println(member.name);
} else {
System.out.println("객체가 없습니다.");
}
참조변수를 사용하기 전에 null 여부를 확인하는 것이 안전합니다.
참조변수의 주소 변경
참조변수는 다른 객체의 주소로 변경할 수 있습니다.
기존에 가리키던 객체는 더 이상 참조되지 않으면 가비지 컬렉터(GC) 가 메모리를 회수합니다.
Member member = new Member("홍길동", 25); // 0x100 주소 저장
member = new Member("김철수", 30); // 0x200 주소로 변경
// 0x100에 있던 "홍길동" 객체는 아무도 참조하지 않음 → GC가 제거
변경 전:
member → 0x100 (홍길동)
변경 후:
member → 0x200 (김철수)
0x100 (홍길동) ← 아무도 참조 안 함 → GC 수거
기본 타입 변수와의 차이
// 기본 타입 - 값 자체 저장
int a = 10;
int b = a; // 값 복사
b = 20;
System.out.println(a); // 10 - a는 그대로
// 참조 타입 - 주소 저장
Member m1 = new Member("홍길동", 25);
Member m2 = m1; // 주소 복사
m2.name = "김철수";
System.out.println(m1.name); // "김철수" - m1도 바뀜
| 구분 | 기본 타입 변수 | 참조변수 |
|---|---|---|
| 저장 내용 | 값 자체 | 힙 메모리 주소 |
| 복사 방식 | 값 복사 (독립적) | 주소 복사 (같은 객체 공유) |
| null 가능 여부 | 불가 | 가능 |
| 주소 없을 때 | 해당 없음 | NullPointerException 발생 |
정리
- 참조변수는 객체 자체가 아닌 힙 메모리의 주소를 저장한다.
- 참조변수는 반드시 주소를 가져야 하며,
null상태에서 객체에 접근하면NullPointerException이 발생한다. - 참조변수를 다른 변수에 대입하면 값이 아닌 주소가 복사되어 같은 객체를 공유하게 된다.
- 참조변수가 다른 주소로 변경되어 아무도 참조하지 않는 객체는 가비지 컬렉터가 자동으로 제거한다.
- 참조변수를 사용하기 전에 항상
null체크를 하는 습관이 중요하다.
'-- 오늘 있었던 개발 일기' 카테고리의 다른 글
| 매개변수(Parameter)란? (1) | 2026.04.11 |
|---|---|
| static 메서드란? - 객체 생성 없이 바로 호출 (0) | 2026.04.09 |
| Object 클래스 - Java 최상위 클래스 (0) | 2026.04.06 |
| 상대경로와 절대경로 (0) | 2026.04.04 |
| 스트림(Stream)이란? - 입출력과 병렬처리 (0) | 2026.04.02 |