Java: String의 불변성 (Immutability)
1. 개요
Java의 String
클래스는 불변 객체(Immutable Object) 로 설계되어 있다.
- 즉, 한 번 생성된 문자열은 절대로 수정되지 않으며, 문자열을 변경하려고 시도하면 항상 새로운 객체가 생성된다.
- 이러한 불변성은 보안, 성능, 스레드 안정성 등 다양한 이유로 매우 중요한 특징이다.
2. 왜 불변(Immutable)한가?
불변성은 단순히 설계 철학이 아니라, 실제 Java 플랫폼의 안정성과 효율성을 위한 필수적인 요소이다.
2.1 보안(Security)
- 문자열은 종종 파일 경로, 데이터베이스 연결 문자열, 네트워크 주소 등에 사용됨.
- 가변 문자열이라면 악의적인 코드가 문자열을 수정해 보안 구멍을 만들 수 있음.
String dbUrl = "jdbc:mysql://localhost";
dbUrl.replace("localhost", "hacker-site.com"); // String은 수정되지 않음
2.2 성능(Performance)
- String Constant Pool을 통해 동일한 문자열을 재사용할 수 있음.
- 이 기능이 제대로 작동하려면 문자열이 절대 바뀌지 않아야 함.
String a = "hello";
String b = "hello";
System.out.println(a == b); // true → 동일 객체 공유
2.3 스레드 안전성(Thread Safety)
- 불변 객체는 내부 상태가 변경되지 않기 때문에, 동기화 없이도 안전하게 공유 가능하다.
- 멀티스레드 환경에서 추가 비용 없이 안정적인 동작 보장.
3. 작동 방식 – 변경은 실제로 “새 객체 생성”
3.1 코드 예시
String a = "hello";
String b = a;
a = a + " world";
System.out.println(a); // hello world
System.out.println(b); // hello
"hello"
는 리터럴 풀에 존재"hello world"
는 Heap에 새로운 객체로 생성- 변수
b
는 여전히"hello"
를 참조
3.2 메모리 구조 흐름
[초기 상태]
a ───▶ "hello"
b ───┘
[수정 후]
a ───▶ "hello world"
b ───▶ "hello"
📌 변경이 아닌 “대체”다. 기존 객체는 절대 바뀌지 않음!
4. 불변 객체의 특징 요약
항목 | 설명 |
---|---|
변경 가능 여부 | ❌ 불가능 – 항상 새로운 객체 생성됨 |
스레드 안전성 | ✅ 동기화 없이 공유 가능 |
공유 가능 여부 | ✅ 문자열 리터럴 풀에서 객체 공유 가능 |
메모리 구조 | Heap 영역 + String Constant Pool 최적화 |
관련 API 특징 |
,
등 모두 새 객체 반환 |
5. 관련 클래스 구분
5.1 불변 객체 (Immutable)
String
Integer
Boolean
LocalDate
,LocalTime
,BigDecimal
5.2 가변 객체 (Mutable)
StringBuilder
StringBuffer
ArrayList
HashMap
📝 불변 클래스는 equals(), hashCode() 재정의에 유리하며, 객체 캐싱 및 보안 측면에서도 장점을 가짐.
6. 성능상의 주의점
6.1 반복 연결 시 성능 저하
String s = "";
for (int i = 0; i < 1000; i++) {
s += "a"; // 매 반복마다 새 객체 생성
}
→ 이 방식은 1000개의 String 객체를 생성함
→ 해결 방법: StringBuilder
사용
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("a");
}
String result = sb.toString();
7. 결론
String
의 불변성은 Java 언어의 안정성과 성능 최적화를 위한 중요한 설계 원칙이다.- 문자열이 자주 변경된다면
StringBuilder
나StringBuffer
를 적극적으로 활용해야 한다. - 불변 객체는 보안성, 공유성, 스레드 안전성 측면에서 뛰어난 장점을 가진다.