자바 공부#1_06. String, StringBuilder, StringBuffer
자바에서 문자열을 다루는 대표적인 클래스는
String, StringBuilder, StringBuffer가 있다.
이 세 가지 클래스는 모두 문자열을 표현할 수 있지만,
내부 동작 방식, 가변성, 멀티스레드 대응 여부, 성능에서 차이가 있다.
1. String (불변 객체)
- String은 불변(immutable) 객체다.
- 한 번 생성되면 값을 변경할 수 없고, 변경 시 새로운 객체가 생성된다.
String str = "hello";
str += " world"; // "hello world"라는 새로운 객체가 생성됨
장점
- 문자열이 변하지 않기 때문에 보안성 높고, thread-safe
- 같은 리터럴은 String Constant Pool에서 재사용되어 메모리 효율성 ↑
단점
- 문자열 변경이 많으면 비효율적
- 반복적으로 문자열을 더하면 객체가 계속 생성되어 성능 저하
String과 관련된 부분은 전 포스트에서 다뤘기 때문에 자세한 내용은 넘어가겠다.
2. StringBuilder & StringBuffer(가변)
StringBuilder와 StringBuffer은 객체의 공간이 부족해지는 경우, 버퍼의 크기를 유연하게 늘려 가변적이다.
두 클래스는 내부 Buffer(데이터를 임시로 저장하는 메모리)에 문자열을 저장해두고 그 안에서 추가, 수정, 삭제 작업을 할 수 있도록 설계되어 있다.
-> StringBuffer / StringBuilder 는 .append(), .delete() 등을 이용하여 동일 객체내에서 문자열 크기를 변경하는 것이 가능하다.
2-1. StringBuilder (비동기)
- 문자열을 자유롭게 수정 가능한 가변 객체
- 내부에서 버퍼를 사용해 문자열을 직접 수정함
- 싱글 스레드 환경에서 가장 빠른 문자열 처리 클래스
StringBuilder sb = new StringBuilder("hello");
sb.append(" world");
System.out.println(sb); // hello world
장점
- 하나의 객체에서 문자열 수정 → 성능 매우 우수
- 가장 가볍고 빠른 문자열 조작 클래스
단점
- 멀티스레드 환경에서는 안전하지 않음
2-2. StringBuffer (동기화 지원)
- StringBuilder와 거의 동일하지만,
- 내부 메서드가 synchronized(동기화) 되어 있어 Thread-safe
StringBuffer sb = new StringBuffer("hello");
sb.append(" world");
System.out.println(sb); // hello world
장점
- 멀티스레드 환경에서도 안정적으로 사용 가능
단점
- 동기화 오버헤드로 인해 StringBuilder보다 성능 ↓
성능 비교 테스트 (10,000회 append)
public class Compare {
public static void main(String[] args) {
long start, end;
String str = "";
start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) str += i;
end = System.currentTimeMillis();
System.out.println("String: " + (end - start) + "ms");
StringBuilder sb = new StringBuilder();
start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) sb.append(i);
end = System.currentTimeMillis();
System.out.println("StringBuilder: " + (end - start) + "ms");
StringBuffer sbf = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) sbf.append(i);
end = System.currentTimeMillis();
System.out.println("StringBuffer: " + (end - start) + "ms");
}
}
✅ 일반적인 결과
- String : 느림 (가장 성능 낮음)
- StringBuffer : 중간
- StringBuilder : 가장 빠름
| 구분 | String | StringBuilder | StringBuffer |
| 불변 여부 | ❌ (불변) | ✅ (가변) | ✅ (가변) |
| 스레드 안전 | ✅ | ❌ | ✅ |
| 성능 | 느림 | 빠름 (최고) | 보통 |
| 사용 환경 | 문자열 변경 거의 없음 | 단일 스레드에서 문자열 조작 많을 때 | 멀티 스레드 환경에서 안전한 문자열 조작 필요할 때 |
결론
✔ 성능이 중요하거나 반복적인 수정이 많은 경우, StringBuilder를 적극적으로 활용
✔ 멀티스레드 상황이 아니면 StringBuffer보다 StringBuilder가 더 효율적이다
그래서 만약 싱글 쓰레드 환경에서나 비동기를 사용할 일이 없으면, StringBuilder를 쓰는 것이 이상적이라 할 수 있다.
하지만 현업에서는 자바 어플리케이션을 대부분 멀티 스레드 이상의 환경에서 돌아가기 때문에 왠만하면 안정적인 StringBuffer로 통일하여 코딩하는것이 좋다. (솔직히 StringBuffer 와 StringBuilder 속도 차이는 거의 미미하다)
- String 을 사용해야 할 때 :
- String은 불변성
- 문자열 연산이 적고 변하지 않는 문자열을 자주 사용할 경우
- 멀티쓰레드 환경일 경우
- StringBuilder 를 사용 해야 할 때 :
- StringBuilder는 가변성
- 문자열의 추가, 수정, 삭제 등이 빈번히 발생하는 경우
- 동기화를 지원하지 않아, 단일 쓰레드이거나 동기화를 고려하지 않아도 되는 경우
- 속도면에선 StringBuffer 보다 성능이 좋다.
- StringBuffer 를 사용해야 할 때 :
- StringBuffer는 가변성
- 문자열의 추가, 수정, 삭제 등이 빈번히 발생하는 경우
- 동기화를 지원하여, 멀티 스레드 환경에서도 안전하게 동작
출처: https://inpa.tistory.com/entry/JAVA-☕-String-StringBuffer-StringBuilder-차이점-성능-비교 [Inpa Dev 👨💻:티스토리]
내가 정리한 것보다 참고 사이트를 보면 더 자세하게 나와있다.
참고: