프로그래밍을 할 때 문자열(String) 은 가장 기본적이면서도 많이 쓰이는 자료형이다.
Java는 문자열을 효율적으로 다루기 위해
이들은 메모리 구조와 동작 방식이 다르기 때문에, 상황에 따라 적절히 선택해야 한다.
| 클래스 | 특징 | 메모리 구조 | 쓰레드 안전성(Thread Safety) |
|---|---|---|---|
| String | 불변(Immutable) 객체 | Heap에 새로운 객체 생성 | 안전 (Thread-Safe) |
| StringBuilder | 가변(Mutable) 객체 | 내부 char 배열 수정 | 안전하지 않음 (싱글 스레드 권장) |
| StringBuffer | 가변(Mutable) 객체 | 내부 char 배열 수정 | 안전 (멀티 스레드 지원) |
String : 변경할 때마다 새로운 객체를 생성한다.
→ 메모리 소모가 크지만, 안정적이고 직관적이다.
StringBuilder : 문자열 수정이 많을 때 빠르다.
→ 싱글 스레드 환경에서 추천.
StringBuffer : StringBuilder와 거의 같지만, 동기화(synchronized) 되어 있어 멀티스레드에서도 안전하다.
// String
String str = "Hello";
str += " World"; // 새로운 객체 생성
// StringBuilder
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 기존 객체 수정
// StringBuffer
StringBuffer sbf = new StringBuffer("Hello");
sbf.append(" World"); // 기존 객체 수정 + 동기화
| 메소드 | 설명 | 예시 |
|---|---|---|
length() | 문자열 길이 반환 | "hello".length() → 5 |
charAt(int index) | 특정 인덱스의 문자 반환 | "hello".charAt(1) → 'e' |
substring(int start, int end) | 부분 문자열 추출 | "hello".substring(1, 4) → "ell" |
indexOf(String str) | 문자열 내 검색 | "hello".indexOf("e") → 1 |
equals(Object obj) | 문자열 비교 | "hello".equals("hello") → true |
toUpperCase() | 대문자로 변환 | "hello".toUpperCase() → "HELLO" |
toLowerCase() | 소문자로 변환 | "HELLO".toLowerCase() → "hello" |
trim() | 앞뒤 공백 제거 | " hello ".trim() → "hello" |
replace(CharSequence old, CharSequence new) | 문자열 치환 | "hello".replace("e", "a") → "hallo" |
substring, replace 같은 메소드는 새로운 객체를 반환한다.charAt, indexOf는 원본 객체를 복사하지 않고 바로 결과를 반환한다 (빠름).| 메소드 | 설명 | 예시 |
|---|---|---|
append(String str) | 문자열 끝에 추가 | sb.append("World") |
insert(int offset, String str) | 특정 위치에 삽입 | sb.insert(5, " Java") |
replace(int start, int end, String str) | 범위 치환 | sb.replace(0, 5, "Hi") |
delete(int start, int end) | 범위 삭제 | sb.delete(0, 2) |
reverse() | 문자열 반전 | sb.reverse() |
toString() | String으로 변환 | sb.toString() |
StringBuilder sb = new StringBuilder("hello");
sb.append(" world"); // hello world
sb.insert(5, " JAVA"); // hello JAVA world
sb.replace(6, 10, "Python"); // hello Python world
sb.delete(5, 12); // hello world
sb.reverse(); // dlrow olleh
System.out.println(sb.toString());
String: 내부에 char[] 배열을 가지고 있고,
한 번 생성되면 내용을 바꿀 수 없는 불변 객체이다.
➔ 값이 바뀌면 새로운 객체를 생성한다. → Heap 메모리 소모 증가.
StringBuilder, StringBuffer:
내부에 char[] 배열과 동적 크기 조정 로직이 있다.
➔ 수정이 발생해도 기존 버퍼를 직접 수정한다.
➔ 용량(capacity)이 다 차면 버퍼 크기를 2배 확장한다. (ArrayList와 유사)
| 상황 | 추천 클래스 |
|---|---|
| 문자열 변경이 거의 없음 | String |
| 문자열 수정이 빈번함 (단일 쓰레드) | StringBuilder |
| 문자열 수정이 빈번함 (멀티 쓰레드) | StringBuffer |
char[]), 메모리 재할당(capacity doubling)을 이해하고 선택해야 한다.