# Java: 기본형(int) vs String(불변 객체)의 메모리 구조 비교
---
## 1. Java의 메모리 구조
Java 프로그램은 크게 세 가지 메모리 공간을 사용한다:
### 1.1 Stack 영역
- ****지역 변수**** 및 ****기본형(primitive type)**** 값 저장
- 메서드 호출 시마다 프레임이 생성되고, 종료되면 자동으로 해제됨
- 매우 빠르며, GC 대상이 아님
### 1.2 Heap 영역
- `new` 연산자 등을 통해 생성된 ****객체****가 저장됨
- `ArrayList`, `String`, `Integer`, 사용자 정의 클래스 등
- GC(Garbage Collector)에 의해 관리됨
### 1.3 String Constant Pool (리터럴 풀)
- Heap 내부의 특별한 공간
- 동일한 문자열 리터럴을 ****공유****하여 메모리 절약
- `"hello"`와 같은 리터럴은 Pool에서 재사용됨
---
## 2. 기본형 변수 (예: `int`)
기본형은 값 그 자체가 ****Stack**** 메모리에 저장된다. 변수 간의 대입은 ****값 복사****이며, 변수 간 영향이 없다.
### 2.1 코드 예시
```java
int a = 10;
int b = a;
a = 20;
```
### 2.2 메모리 흐름
```text
초기 상태:
[Stack]
a → 10
b → 10 (값 복사됨)
a = 20; 이후:
a → 20
b → 10 (영향 없음)
```
📌 `int`는 ****값 자체(value)**** 를 저장하며, 변수 간 대입은 ****값 복사****다.
값을 변경해도 ****기존 변수나 참조에 영향을 주지 않는다.****
---
## 3. String (불변 객체)
`String`은 ****참조형(reference type)**** 객체이며, Stack에는 참조만 저장되고 ****실제 문자열은 Heap 또는 Constant Pool에 존재****한다.
### 3.1 코드 예시
```java
String s1 = "hello";
String s2 = s1;
s1 = s1 + " world";
```
### 3.2 메모리 흐름
```text
[초기 상태]
[Stack] [Heap (String Pool)]
s1 ─┐ "hello"
└────────▶
s2 ─┘ (s1, s2 둘 다 "hello" 참조)
[변경 후]
[Stack] [Heap]
s1 ──────────▶ "hello world" ← 새 객체 생성
s2 ──────────▶ "hello" ← 원본 유지
→ s1 + " world" 는 기존 "hello"를 수정하는 것이 아니라
**"hello world"라는 새로운 객체를 생성**
```
📌 `String`은 ****불변(immutable)**** 이기 때문에 수정이 아닌 ****새 객체 생성**** 방식으로 동작한다.
따라서 ****반복 수정이 많으면 Heap에 객체가 누적 → GC 부담 증가**** 가능.
---
## 4. 예제 비교 요약
```java
// 기본형
int a = 10;
int b = a;
a = 20; // b는 여전히 10
// 참조형 (String)
String s1 = "hi";
String s2 = s1;
s1 = s1 + "!"; // s2는 여전히 "hi"
```
항목
| 기본형 (int 등)
| 참조형 (String)
|
---|
저장 위치
| Stack
| Stack(참조), Heap(객체)
|
대입 방식
| 값 복사
| 참조값 복사
|
수정 시 영향
| 원본과 무관
| 불변 → 새 객체 생성
|
메모리 부담
| 없음
| 반복 수정 시 Heap 객체 증가 가능
|
---
## 5. 요약 및 실무 팁
- 🔹 ****기본형****은 값 자체를 Stack에 저장 → 변경 간섭 없음, 매우 빠름
- 🔹 ****String****은 참조형이며 불변 → 수정 시 마다 새 객체 생성
- 🔸 반복적인 문자열 연결/수정이 필요한 경우 → **`StringBuilder` **사용이 권장됨****
```java
// 비효율 (String)
String result = "";
for (int i = 0; i < 1000; i++) {
result += "a"; // 1000개 객체 생성
}
// 효율적 (StringBuilder)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("a");
}
String result = sb.toString(); // 단 1개 객체 사용
```
---
## 6. 관련 참고
- 불변 객체: `String`, `Integer`, `Boolean`, `LocalDate`
- 가변 객체: `StringBuilder`, `ArrayList`, `HashMap`
📌 ****불변성 덕분에 String은 안정적이고 안전하지만, 반복 수정 시에는 가변 객체 사용이 메모리 효율에 유리하다.****
### 1. Java 의 메모리 구조
세 가지 메모리 영역
- Stack : 지역 변수, 기본형 변수 저장 (`int`, `boolean`, etc)
- Heap : `new` 키워드나 객체 생성 시 사용 (`String`, `ArrayList`, etc)
- String Constant Pool : 같은 문자열 리터럴을 재사용하는 공간 (Heap 내부 특수 영역)
### 2. 기본형 변수(int 등)
값 자체가 Stack에 저장됨
```
int a = 10;
int b = a;
a = 20;
```
📌 메모리 흐름:
```
[Stack]
a → 10
b → 10 (복사됨)
a = 20; 이후
a → 20
b → 10 (영향 없음)
```
- int는 값(value) 자체가 저장되므로 대입 시 값만 복사됨
- 변경해도 다른 변수에 영향 없음
### 3 . String (불변 객체)
참조값이 Stack에, 실제 값은 Heap/String Pool에 저장
```
String s1 = "hello";
String s2 = s1;
s1 = s1 + " world";
```
📌 메모리 흐름:
```
초기 상태:
[Stack] [Heap (String Pool)]
s1 ─┐ "hello"
└────────────▶
s2 ─┘
변경 후:
[Stack] [Heap]
s1 ──────────────▶ "hello world" ← 새 객체 (불변성)
s2 ──────────────▶ "hello" ← 원본은 그대로 유지
```
- s1 + " world"는 기존 문자열을 수정하지 않고, 새로운 문자열 객체 생성
- 기존 "hello"는 s2가 여전히 참조 중
- 따라서 메모리 활용방식이 더 복잡 (GC 대상 증가 가능)
### 4. 예제 비교
```java
// 기본형
int a = 10;
int b = a;
a = 20; // b는 여전히 10
// String
String s1 = "hi";
String s2 = s1;
s1 = s1 + "!"; // s2는 여전히 "hi"
```
- 기본형은 값 그 자체를 다루고, 수정 시 그냥 덮어쓰기
- String은 객체의 참조를 다루며, 수정 시 새 객체 생성 = 불변성 유지
이 불변성 덕분에 String은 안정적이고 안전하지만, 반복 수정이 많을 땐 StringBuilder를 쓰는 게 더 효율적이다.
---