본문 바로가기
-- 오늘 있었던 개발 일기

참조변수는 주소를 가져야 한다!

by code study 2026. 4. 8.

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 체크를 하는 습관이 중요하다.