
자바에서는 문자열을 다루기 위해 String, StringBuffer, StringBuilder 세 가지 클래스를 사용합니다.
오늘은 각 클래스의 특징, 동작 방식, 성능, 스레드 안정성, 그리고 상황별 선택 기준을 비교해볼게요!
이 글을 통해 아래와 같은 것들을 이해해볼 수 있을거에요!
String이 불변(Immutable) 객체인 이유StringBuffer와StringBuilder의 필요성과 차이- 상황에 맞는 문자열 클래스 선택 방법
String — 불변(Immutable)한 문자열
String 객체는 한 번 생성되면 내부 값이 변경되지 않는 불변(Immutable) 객체입니다.
이 덕분에 자바는 문자열을 String Pool에 저장하고, 동일한 문자열 리터럴을 재사용할 수 있습니다.
String str1 = "abc";
String str2 = "abc";
System.out.println(System.identityHashCode(str1) == System.identityHashCode(str2)); // true
String str3 = new String("abc");
System.out.println(System.identityHashCode(str1) == System.identityHashCode(str3)); // false
위 예제에서 str1과 str2는 같은 객체를 공유하지만, str3은 새로 생성된 별도의 객체입니다.
특징은 다음과 같아요
- 불변성: 생성 후 내용 변경 불가
- 메모리 효율: 동일한 문자열은 String Pool에서 재사용
- 단점: 문자열 결합(
+)시마다 새로운 객체가 생성되어 성능 저하 가능
따라서 문자열 변경이 거의 없는 경우 (예: 상수, 로그 메시지, 키 값 등) 혹은 읽기 전용으로 문자열을 사용할 때 사용하는 것이 좋아요.
StringBuffer — 가변(Mutable)하며 스레드 안전(Thread-safe)
StringBuffer는 String과 달리 가변(Mutable) 객체입니다.
새로운 객체를 생성하지 않고 내부 버퍼를 수정하여 문자열을 변경할 수 있습니다.
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Hello World
특징은 다음과 같아요
- 가변성: 문자열 변경 가능 (
append,insert,delete등 지원) - 스레드 안전성: 모든 메서드가
synchronized로 동기화되어 멀티스레드 환경에서도 안전 - 단점: 동기화 처리로 인해 단일 스레드 환경에서는 상대적으로 느림
따라서 여러 스레드가 동시에 문자열을 조작해야 하는 경우, 동시성 문제 없이 문자열을 안전하게 처리해야 할 때 사용하는 것이 좋습니다.
StringBuilder — 가변(Mutable)하지만 스레드 비안전(Non-thread-safe)
StringBuilder는 StringBuffer와 거의 동일하지만, 동기화 처리(synchronization)가 제거된 버전입니다.
따라서 단일 스레드 환경에서 가장 빠른 문자열 조작 성능을 제공합니다.
StringBuilder sb = new StringBuilder("Hi");
sb.append(" there");
System.out.println(sb); // Hi there
특징은 다음과 같아요
- 가변성: 문자열 변경 가능 (
StringBuffer와 동일한 API 제공) - 성능: 동기화가 없어 가장 빠름
- 단점: 멀티스레드 환경에서는 안전하지 않음
따라서 단일 스레드 환경에서 문자열을 자주 조합하거나 수정할 때, 많은 문자열 연결, 파싱, 텍스트 생성 작업이 필요한 경우 사용하는 것이 유리합니다.
저는 코딩 테스트 문제를 풀 때 애용하는 것 같아요!
String vs StringBuffer vs StringBuilder
표로 정리해서 비교해볼까요?
| 구분 | String | StringBuffer | StringBuilder |
| 변경 가능 여부 | ❌ 불변 | ✅ 가변 | ✅ 가변 |
| 스레드 안전성 | ✅ 안전 | ✅ 안전 | ❌ 위험 |
| 성능 | 느림 (새 객체 생성) | 중간 (동기화 비용) | 빠름 |
| 권장 환경 | 상수, 로그, 읽기 전용 문자열 | 멀티스레드 환경 | 단일 스레드 환경 |
따라서 문자열이 거의 변하지 않는 상황엔 String을 사용하여 불변성으로 메모리 절약 및 안전성을 확보하도록 하고,
멀티스레드 환경에서 문자열을 수정할 때 StringBuffer의 동기화로 안전하게 처리하고,
단일 스레드에서 문자열을 자주 수정하는 경우 StringBuilder로 빠르게 처리하는 것이 좋겠네요!
상황에 맞는 클래스를 선택하면 코드의 성능과 안정성을 모두 확보할 수 있습니다.
작은 선택 하나가 프로그램의 효율을 크게 바꾼다는 점, 꼭 기억해보면 좋을 것 같아요!
'Language > Java ☕️' 카테고리의 다른 글
| Java static 키워드 완전 가이드 (0) | 2024.05.22 |
|---|---|
| 자바 메모리 구조 이해하기 (0) | 2024.05.22 |
| 자바의 가비지 컬렉션(GC) 한 번에 이해하기 (0) | 2024.02.02 |
| Double과 Float를 사용하면 안되는 이유 (0) | 2024.02.01 |
| JDK, JRE, JVM의 차이와 자바 실행 구조 이해하기 (0) | 2024.02.01 |
안녕하세요, 저는 주니어 개발자 박석희 입니다. 언제든 하단 연락처로 연락주세요 😆