String은 불변이다
- String 클래스는 내부적으로 Final 키워드가 선언된 byte[] 필드를 사용해서 문자열을 저장한다
- String은 참조 타입, 즉 Reference Type이므로 concat(), replace(), toUpperCase() 사용시 새로운 String 객체를 참조한다 (불변유지)
왜 String은 불변이어야 했을까
String Constant Pool

SCP를 먼저 얘기하자면 String Constant Pool자체는 JVM의 Heap 영역 안의 특별 공간이다
→ 동일한 문자열 리터럴이 여러번 등장해도 메모리를 한 번만 사용하도록 관리하는 구조!
구조를 도식화 하자면
[In Code]
  ...
  String a = "hello"
  String b = "hello"
  String c = "world"
  ...
[JVM]
┌──────────────────────────────────┐
│            Heap Area             │
│   (힙 영역 – 객체들이 저장되는 곳)      │
├──────────────────────────────────┤
│                                  │
│     String Constant Pool (SCP)   │
│      ┌──────────────────────┐    │
│      │   "hello" ────┐      │    │
│      │               │      │    │
│      │   "world"     │      │    │
│      │   "java"      │      │    │
│      └──────────────────────┘    │
│          ↑          ↑            │
│          │          │            │
│   ┌──────┘          └──────┐     │
│   │                        │     │
│ String a ──────────────→ "hello" │
│ String b ──────────────→ "hello" │
│ String c ──────────────→ "world" │
└──────────────────────────────────┘위처럼, String a, b, c가 각각 만들어진다고 치자.
a가 “hello”를 생성했고, 그 뒤의 b는 SCP에 hello가 있음을 확인하고 기존의 hello를 참조하게 된다
멀티스레드 환경에서의 Thread-safe
불변한 객체는 멀티 스레드 환경에서 thread-safe 하니까!
문자열의 변경이 일어난다면 SCP가 새로운 객체를 생성할 거고 이는 동기화에 신경 쓸 필요가 없어진다.
해시코드의 해싱
해시코드를 한 번만 계산하고 이를 Cashing해서 재사용하게 된다.
민감 정보의 보호
변경 불가능하니까! 수정방지되니까!
String에 대한 리터럴 생성과 생성자 생성의 차이
// 리터럴 생성
String str1 = "hello";
// 생성자 생성
String str2 = new String("hello");
// 참조 확인용
String str3 = "hello";
리터럴로 생성한 String 객체
- Heap 영역의 SCP에 저장되어 동일한 문자열을 재사용할 수 있는 상태다
- 즉, str1로 만든 객체는 str3이 참조하게 된다
System.out.println(System.idntityHashCode(str1));
// 출력: 245846322
System.out.println(System.idntityHashCode(str3));
// 출력: 245846322생성자로 생성한 String 객체
- Heap 영역에서 새로운 객체를 생성한다
System.out.println(System.idntityHashCode(str2));
// 출력: 485321448번외, intern() 사용하기
intern()을 사용하면 heap 영역에 저장된 String 객체를 SCP에 저장할 수 있다
정확히는 SCP 존재시 그 주솟값을 반환하고, 없을 경우 String SCP에 추가하여 새로운 주솟값을 반환한다
String str1 = new String("hello"); // SCP 저장 아님
String str2 = str1.intern(); // SCP 저장시키고 새로운 주소값 반환
String str3 = "hello"; // str2가 만든 "hello"의 주소값 가짐
System.out.println(str1 == str2); //false
System.out.println(str2 == str3) // true
 
				