💡 String과 String buffer는 무슨 차이가 있을까?
String과 Stringbuffer의 차이점을 아나요? 라는 질문을 받았다.
면접때는 답하지 못했지만 지금 이렇게라도 정리해본다.
String | String Buffer | String Builder | |
Storage Area | Constant String Pool | Heap | Heap |
Modifiable | No (immutable) | Yes (mutable) | Yes (mutable) |
Thread Safe | Yes | Yes | No |
Performance | Fast | Slow | Fast |
String
The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.
자바에서 String은 character of strings
를 뜻한다. Java에선 String이 클래스다. 따라서, "abc"같은 문자열이 있다면 이건 String 클래스의 인스턴스다. 즉, String은 참조형이라는 것.
또한 String은 불변이다. 자바 레퍼런스에 보면 constant
라고 써져있다.
한 번 만들어진 이후에 변하지 않는다.
String str = "abc";
이 코드와
char data[] = {'a','b','c'};
String str = new String(data);
이 코드는 같은 의미다.
또한, Java의 모든 immutable한 객체는 thread safe하다. 따라서 String도 thread-safe하다. String can not be used by two threads simultaneously.
methods
String 클래스는 문자열을 조작하는 다른 메소드들도 가지고 있다. compare, substring, copy, upper등등.
또한 concat('+' 연산자) 과 '다른 오브젝트 -> string'으로 변환하는 기능도 지원한다.
String의 concatenation은 StringBuilder
(or StringBuffer
) 클래스와 거기있는 append
메소드에서 따왔다.
❔❓ 불변인데 어떻게 +나 append를 사용할수 있는거지?
+나 append를 사용하면, 새로 만든 문자열을 가리키게 된다.
예를 들어, str= "hello" 였는데, str = str + "world"를 하면
str 내용을 바꾸는 것이 아니고, 새로운 "hello world"라는 문자열을 가리키게 된다.
그리고 이전에 남아있던 "hello"는 gc가 처리한다. (heap영역에 있는 데이터는 gc가 알아서 처리)
String을 사용할땐 모두 인스턴스라고 했으니, "hello"같은건 heap에 저장되어 있었겠지?
아 그러니 같은 문자열 내용이라도 주소가 다르니 ==로 검사하면 다르다는 결과가 나왔었구나.
❔❓ String에 연산을 자주 사용한다면?
그만큼 heap에 garbage가 많이 생긴다. => 성능 저하로 이어짐!
그런데 막상 String이 항상 heap에 매번 저장되는 것은 아니다. String은 immutable한 특성을 이용하여 string pool 이라는 개념을 도입했다.
String을 저장할때 ""로 초기화한 리터럴은 heap의 String pool
에 저장이 된다.
""로 초기화한 리터럴의 값이 같으면, string pool 의 같은 주소를 가리키게 된다. 아래 사진처럼.
s1과 s2는 같은 "Cat"을 가리키고, new를 이용한 s3는 새로운 메모리 주소를 가리킨다.
그러면 new로 생성한 객체를 다시 String constant pool 로 옮기는 방법은 없을까?
있다. intern() 메소드를 이용하면 된다. str.intern()을 이용하면 heap에 있는 객체를 String pool 안으로 옮긴다.
StringBuffer
thread-safe, mutable sequence of characters
String은 불변인 반면, StringBuffer는 mutable하다. modified가능이라는 말~ 변환가능!
StringBuffer는 multiple threads에 안전하다. 메소드들의 sync를 맞춰주기 때문이다.
특정 인스턴스와 관련된 각 스레드에서, 메소드 호출 순서와 일치하는 순서대로 동작하게끔 보장한다.
methods
StringBuffer의 기본 메소드는 append
와 insert
다. append
는 끝에, insert
는 특정 위치에 characters를 붙인다.
string buffer를 sb라고 줄여서 표현했을때
sb.append(x)
는 sb.insert(sb.length(), x)
와 같다.
String Buffer도 C++의 vector에서 봤던것처럼 capacity
가 있다. 문자열의 길이가 capacity를 넘어가면 stringbuffer는 internal overflow가 일어난다. 그러면 자동으로 버퍼의 크기를 늘린다.
JDK 5버전 StringBuffer부터는 StringBuilder 클래스를 이용하도록 보완됐다. StringBuilder는 StringBuffer와 똑같은데, 다만 싱글 스레드 용도라서 sync를 보장하지 않는다. 대신 더 빠르다.
StringBuilder
StringBuilder는 Stringbuffer와 비슷하다. 그냥 synchronization을 보장하지 않는 StringBuffer라고 생각하면 된다.
mutable하고, single thread 용도로 쓴다.
이 클래스는 StringBuffer클래스를 single thread에서 사용할때, drop-in replacement로 사용된다. 그리고 Stringbuilder가 Stringbuffer보다 빠르다.
참고
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html
https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html
https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html
https://www.journaldev.com/797/what-is-java-string-pool
'Study > Web' 카테고리의 다른 글
css 상속 (0) | 2020.08.29 |
---|---|
C++ 배열, vector, array JS 배열 정리 (0) | 2020.07.23 |
[CSS] flex-box 안 items 크기가 안 변할때 (0) | 2020.05.24 |
[JS] set에 배열를 넣으면 중복으로 넣어지는 문제 (0) | 2020.05.21 |
[js] 클래스 안 EvnetListener에서 클래스에 있는 메소드 이용하기 (0) | 2020.05.16 |