Java 참조 타입(Reference Type)과 객체 참조 완벽 이해하기
Java를 공부할 때 정말 많이 헷갈리는 개념이 바로:
참조 타입(Reference Type)
입니다.
특히 초보 시절에는:
User a = new User();
User b = a;
이 코드가:
객체 복사인가?
주소 복사인가?
매우 헷갈립니다.
실무에서도:
- 객체 수정 Side Effect
- 얕은 복사(Shallow Copy)
- 깊은 복사(Deep Copy)
- Collection 복사 문제
- 동시성 문제
까지 전부 참조 구조와 연결됩니다.
이번 글에서는:
- 참조 타입이란 무엇인가
- 객체 참조 구조
- Java 메모리 흐름
- Call By Value 진실
- 얕은 복사 / 깊은 복사
까지 JVM 메모리 관점으로 깊게 정리해보겠습니다.
1. Java 타입은 크게 2가지
Java 타입은:
| 구분 | 종류 |
| Primitive Type | int, long, double 등 |
| Reference Type | 객체 타입 |
2. Primitive Type
primitive는:
값을 직접 저장하는 타입
입니다.
예시:
int a = 10;
메모리:
Stack:
a = 10
즉 값 자체 저장.
3. Reference Type
참조 타입은:
객체 주소(reference)를 저장하는 타입
입니다.
예시:
User user = new User();
4. 메모리 구조
Stack:
user -> 0x1000
Heap:
0x1000 -> User 객체
즉:
Stack = 주소값
Heap = 실제 객체
입니다.
5. 가장 중요한 핵심
매우 중요합니다.
User user
이 변수는:
객체 자체가 아니다
즉:
객체 위치를 가리키는 참조값(reference)
입니다.
6. 객체 참조 예시
User a = new User();
User b = a;
메모리:
Stack:
a -> 0x1000
b -> 0x1000
Heap:
0x1000 -> User 객체
즉:
같은 객체 참조 중
입니다.
7. 그래서 한쪽 수정 시 영향 발생
b.name = "Kim";
하면:
a.name
도 변경됨.
왜냐하면:
같은 Heap 객체
를 바라보기 때문.
8. Java는 포인터인가?
Java는:
직접 포인터는 숨김
구조입니다.
하지만 내부적으로는 사실상:
reference 기반 주소 구조
사용.
9. 왜 포인터를 숨길까?
C/C++처럼 직접 메모리 접근 허용하면:
- 메모리 오염
- 시스템 충돌
- 보안 문제
위험 증가.
Java는:
안전한 reference 추상화
사용.
10. null이란?
User user = null;
의미:
참조 대상 없음
즉:
아무 객체도 가리키지 않음
상태.
11. NullPointerException 원인
user.name
실행 시:
참조 대상 없음
→ NullPointerException 발생.
12. 객체 비교 ==
매우 중요합니다.
a == b
의미:
같은 객체 참조인가?
입니다.
13. 예시
User a = new User();
User b = new User();
결과:
a == b
↓
false
왜냐하면:
Heap 객체가 서로 다름
14. equals()와 차이
equals()
는:
논리적 동등성 비교
입니다.
즉:
- 값 비교 가능
- 내용 비교 가능
15. String 비교 실수
안 좋은 예:
String a = new String("Java");
String b = new String("Java");
a == b
결과:
false
왜냐하면:
다른 객체
이기 때문.
16. String equals()
a.equals(b)
↓
true
내용 비교 수행.
17. 메서드 호출 시 객체 전달
예시:
change(user);
많이 헷갈리는 부분.
18. Java는 Call By Value
매우 중요합니다.
Java는:
무조건 Call By Value
입니다.
19. 그럼 왜 객체 변경이 될까?
예시:
void change(User user) {
user.name = "Kim";
}
이유:
reference 값 자체를 복사
하기 때문.
20. 메모리 흐름
원본:
user -> 0x1000
복사:
parameter -> 0x1000
즉:
같은 객체 참조
중.
21. 하지만 참조 자체 변경은 영향 없음
void test(User user) {
user = new User();
}
이 경우:
지역 변수 reference만 변경
입니다.
원본 영향 없음.
22. 매우 중요한 차이
| 동작 | 원본 영향 |
| 객체 내부 수정 | O |
| 참조 재할당 | X |
23. 얕은 복사(Shallow Copy)
얕은 복사는:
reference만 복사
하는 것.
예시:
User b = a;
24. 얕은 복사 메모리 구조
a -> 0x1000
b -> 0x1000
즉:
같은 객체 공유
25. 얕은 복사 문제
한쪽 수정 시:
다른 쪽 영향 발생
가능.
실무에서 매우 중요.
26. 깊은 복사(Deep Copy)
깊은 복사는:
새로운 객체를 새로 생성하여 복사
하는 것.
27. 깊은 복사 예시
User copy = new User();
copy.name = original.name;
메모리:
original -> 0x1000
copy -> 0x2000
28. Collection 얕은 복사 문제
대표 사례:
List<User> copy =
new ArrayList<>(original);
주의:
List만 새 객체
내부 User는 같은 참조
입니다.
29. 실무에서 매우 많이 터지는 문제
대표 사례:
- DTO 수정 영향
- 캐시 데이터 오염
- 멀티스레드 공유 문제
- Collection 내부 객체 변경
30. Immutable Object가 중요한 이유
불변 객체는:
객체 수정 자체 불가능
즉:
- Side Effect 감소
- Thread-safe 향상
가능.
31. String은 왜 immutable일까?
대표 이유:
공유 안전성
입니다.
예:
String a = "Java";
String b = a;
같은 객체 공유 가능.
32. 참조 타입 종류
대표 참조 타입:
| 타입 | 예시 |
| 클래스 | User |
| 배열 | int[] |
| 인터페이스 | List |
| enum | Role |
33. 배열도 참조 타입
int[] arr = new int[3];
메모리:
Stack:
arr -> 0x1000
Heap:
배열 객체
34. 다형성과 reference
예시:
Animal animal = new Dog();
Stack:
animal -> Dog 객체 주소
즉:
참조 타입은 부모
실제 객체는 자식
가능.
35. 실무에서 자주 하는 실수
1) 객체 복사와 참조 복사 혼동
User b = a;
객체 복사 아님.
2) equals 대신 == 사용
특히 String 비교 문제 매우 흔함.
3) Collection 복사 시 깊은 복사 착각
실제로는 대부분 shallow copy.
36. 핵심 흐름 요약
reference 변수
↓
Heap 객체 주소 저장
↓
실제 객체 접근
37. 가장 중요한 핵심 한 줄
Java 객체 변수는
객체 자체가 아니라
reference를 저장한다
38. 정리
참조 타입(reference type)은 단순 문법 개념이 아닙니다.
실제로는:
- 객체 메모리 구조
- JVM Heap/Stack
- 객체 공유
- 얕은 복사/깊은 복사
- Side Effect
- GC
전체와 연결되는 매우 중요한 개념입니다.
특히 실무에서는:
- reference 구조
- equals vs ==
- shallow/deep copy
- immutable 객체
를 정확히 이해하는 것이 매우 중요합니다.
다음 글에서는:
String Pool 원리
를 intern(), 문자열 최적화, immutable 구조, JVM Constant Pool까지 포함해서 깊게 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java Garbage Collector(GC) 원리 완벽 이해하기 (0) | 2026.05.26 |
|---|---|
| Java String Pool 원리 완벽 이해하기 (0) | 2026.05.26 |
| Java 객체 생성 과정과 메모리 흐름 완벽 이해하기 (0) | 2026.05.26 |
| Java Stack / Heap / Method Area 메모리 구조 완벽 이해하기 (0) | 2026.05.26 |
| Java ClassLoader 동작 원리 완벽 이해하기 (0) | 2026.05.26 |
댓글