# 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를 쓰는 게 더 효율적이다. ---