-
[Java] String 🆚 StringBuffer 🆚 StringBuilder 무슨 차이일까?Programming/Java 2021. 7. 23. 21:53
"String, StringBuilder, StringBuffer의 차이에 대해 설명하세요" 라는 면접 빈출 질문이 있다고 한다
그래서 오늘 java 공식 api 문서를 보면서 세 가지 클래스의 차이를 정리해 볼 것이다
1. String
String 클래스는 character 자료형으로 된 문자열을 표현하는 대표적인 클래스이다. "abc"와 같이 큰따옴표로 표현될 수 있는 문자열이 String 클래스의 구현체이다.
"abc"와 같은 문자열 value 자체는 값이 생성된 뒤에 변하지 않는 상수이다.
변수 할당 후 값을 자유롭게 바꿀 수 있는 Numeric형 변수들과 다르게, String의 문자열 value 자체는 바뀔 수 없다. 즉, Immutable한 속성을 가지고 있다는 것인데 설명은 아래의 링크를 참조하자
https://www.javatpoint.com/immutable-string
따라서 많은 언어들이 문자열을 표현하기 위해 String형 배열(Buffer)를 사용하곤 한다.
String str = "ijin" char data[] = {'i', 'j', 'i', 'n'}; String str2 = new String(data); //equivalent to str1
이렇게 char형 배열을 사용하여 String으로 변환함으로써 문자열을 표현할 수 있다.
String 클래스는 문자열 활용을 위해 문자열 비교, 문자열 검색, 부분 문자열 추출, 문자열 복사 혹은 대문자/소문자 변환 등 다양한 메소드들을 지원한다.
String str = "abc" + "def"; StringBuilder str2 = new StringBuilder("abc").append("def"); //equivalent to str
문자열 연산에 제한적인 C언어와는 다르게, '+'를 이용한 concatenation 연산이나 다른 Object로의 변환을 지원해주기도 한다. 해당 연산은 StringBuilder 혹은 StringBuffer의 append() 메소드로도 대체할 수 있다.
Object 클래스(및 Object 클래스를 상속받은 모든 클래스)에서 toString() 메소드를 사용하면 String 객체로 conversion이 가능해진다.
Method Type and Definition Method Description char charAt(int index) index 번째에 있는 char 변수를 반환 int compareTo(String anotherString) 기준 String과 인자 String을 비교한 값을 int 형식으로 반환 String concat(String str) 기존 String에 인자 String을 더해서 반환 boolean contains(CharSequence s) char s를 포함하고 있는지 반환 boolean equals(Object anObject) 인자 객체와 기존 String이 같은지 비교 int hashCode() 해당 String의 hashCode 값을 반환 int length() 해당 String의 길이를 반환 String[] split(String regex) 인자 String을 기준으로 기존 String을 분할하여 배열로 반환 String substring(int beginIndex, int endIndex) beginIndex부터 endIndex까지의 부분문자열을 반환 2. StringBuffer
StringBuffer는 공식 API 문서의 첫 소개에 A thread-safe, mutable sequence of characters 라는 문장이 있다.
String과 유사하게 문자열을 표현하는 데에 사용되지만 수정될 수 있다는 점이 특징이다. 즉, StringBuffer가 표현하는 문자열의 내용과 길이는 메소드 호출에 의해 언제든지 바뀔 수 있다.
StringBuffer는 멀티 쓰레드 환경에서도 동기화 되기 때문에 안전하다. 특정 객체가 수행하는 모든 작업은 멀티 쓰레드 환경에서의 호출 순서와 일치하게끔 동작한다.
주요 연산인 append와 insert는 모든 객체를 인자로 받을 수 있으며, append는 문자열의 맨 뒤에 insert는 지정한 특정 위치에 데이터를 추가한다.
멀티 쓰레드 환경에서 사용하기에 안전하도록 설계되었지만 모든 상황에서의 안전을 보장하는 것은 아니다.Constructor(생성자) 또는 추가/삽입 연산이 쓰레드 간에 동일한 소스 시퀀스에 접근할 경우, 호출하는 코드가 연산을 수행하는 동안 일관되고 변하지 않도록 감시해야 한다. 이는 호출하는 측에서 작업을 수행하는 동안 lock을 걸거나, 변경 불가능한 소스 시퀀스를 사용하거나, 소스 시퀀스를 공유하지 않음으로써 가능하다.
모든 StringBuffer는 capacity를 가지고 있다. 이전에 소개한 글(vector가 capacity를 1.5배 씩 늘려주는 이유)에서 언급한 것 처럼, 내부 capacity를 초과할 경우 메모리를 스스로 재할당한다.
3. StringBuilder
StringBuilder 또한 변할 수 있는 문자열을 저장하는 클래스이다.
특이하게도 StringBuffer와 대부분 동일한 API를 제공하지만 단일 스레드 환경에서 사용하도록 설계되었기 때문에 동기화를 보장하지 않는다.
정리 💡
String 클래스는 StringBuffer/StringBuilder 클래스와 달리 불변성을 가지고 있다.
StringBuffer 클래스는 단일 쓰레드 환경에서 사용하도록 설계된 StringBuilder의 단점을 보완하기 위해 등장했다.
StringBuilder 클래스와 동일한 연산을 모두 지원하지만 StringBuilder는 동기화를 수행하지 않기 때문에 더 빠르다.
따라서 해당 클래스를 사용하는 환경이 단일 쓰레드/멀티 쓰레드인지에 따라 선택해야 할 것이다.
참고자료:
- https://docs.oracle.com/javase/8/docs/api/java/lang/String.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html
- https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html'Programming > Java' 카테고리의 다른 글
[Java] Primitive Data Types (336) 2021.08.22 [Java] Abstract Class(추상 클래스)와 Interface(인터페이스)의 차이 (277) 2021.08.15 [Java] Java API HashMap은 어떻게 동작할까 (0) 2021.06.20 [Java] Primitive Wrapper Class (0) 2021.04.13 [Java] Comparable과 Comparator (0) 2021.04.06