왜 String 를 그냥 사용하면 안될까?
String 은 immutable 하다. 즉, 변하지 않는다는 뜻이다.
String str = "hello";
str = "hello world";
위와 같이 "hello"
를 담고 있는 str
변수에 "hello world"
를 대입해주면 어떻게 될까?
"hello"
가 있던 공간에 world
를 추가해주는 것이 아니라 "hello world"
라는 새로운 문자열이 있는 메모리 공간을 str
이 가리키게 되는것이다.
String str = "hello world";
str.replace("hello", "hi");
System.out.println(str); // hello world
위 코드의 출력 결과는 어떨까? "hi world"
일까? 아니다. 여전히 "hello world"
이다.
replace
함수를 호출 했다 하더라도 str
은 변하지 않는다. 왜냐하면 string 은 immutable 하기 때문이다.
만약 바뀐 문자열을 가지고 싶다면 replace
함수의 리턴 해주는 문자열을 받아야 한다.
String str = "hello world";
str = str.replace("hello", "hi");
System.out.println(str); // hi world
string 의 toUpperCase()
, subString()
등등 다른 함수들도 마찬가지이다. 모두 그러한 연산들이 적용된 새로운 문자열을 리턴해주지 문자열 그 자체를 바꾸지는 못한다.
String str = "";
for (int i=0; i<1000000; i++){
str += "a";
}
그렇다면 위 연산을 하면 어떻게 될까? 새로운 문자열을 1000000 번이나 새롭게 String 객체를 만들고 주소값이 1000000 번 바뀌게 된다. 상상만 해도 메모리 효율이 매우 나쁠 것이다. 따라서 String 연산을 매우 많이 반복해야 하는 경우에는 String 보다는 StringBuilder 나 StringBuffer 를 사용하는 것이 좋다.
StringBuilder 와 StringBuffer
이 둘은 mutable 하다. 즉, 변경이 가능하다. StringBuilder / StringBuffer 는 미리 메모리 공간을 확보해두기 때문에 (특정 크기의 char 배열을 만들어두기 때문에) toString()
를 통한 immutable String 을 리턴하기 전까지는 메모리 공간 안에서 char 를 추가하고 변경하고 삭제할 수 있다.
그렇다면 이 둘의 차이점은 뭘까??
- StringBuilder
- 비동기적
- 스레드 세이프 하지 못하다.
- StringBuffer 에 비해 효율적이다.
- StringBuffer
- 동기적
- 스레드 세이프
- StringBuilder 에 비해 효율이 떨어짐