개발을 하면서 가장 많이 사용하는/했던 String
에 대해서 알아보고자 합니다.
String은 immutable(불변)
특성이 있습니다. 따라서, 한 번 할당한 문자열은 똑같은 주소만을
가지게 되고, 더하기 연산을 하면 새로운 객체가 생성되어 재할당
됩니다.
String str = "hello";
System.out.println(str.hashCode()); // 99162322
str = str + " world";
System.out.println(str.hashCode()); // 1794106052
String은 2가지 생성 방식이 있고, 각각의 차이점이 있습니다.
new : Heap영역
에 값을 저장합니다.
literal : Heap영역
내부에 존재하는 String constant pool영역
에 값을 저장합니다.
String strLiteral = "value";
String strNew = new String("value");
따라서, 2가지 방식을 비교 연산한다면, 아래와 같은 값을 얻을 수 있습니다.
== : 객체의 주소 값
을 비교합니다.
equals : 객체의 문자열 값
을 비교합니다.
strLiteral == strNew ? false
strLiteral.equals(strNew) ? true
StringBuilder는 mutable(가변)
특성이 있습니다. 따라서, 더하기 연산을 해도 같은 객체에 할당
됩니다.
StringBuilder str = new StringBuilder("hello");
System.out.println(str.hashCode()); // 1304836502
str.append(" world");
System.out.println(str.hashCode()); // 1304836502
JDK 1.5
이상에서는 String도 += 연산이 컴파일 단계에서 내부적으로 StringBuilder로 변경
되어 동작합니다.
하지만, 아래와 같이 반복문에서 사용한다면, 불필요한 StringBuilder 객체가 생성되므로 성능에 영향을 미칠 수 있습니다.
String[] arr = new String[5];
arr[0] = "hello";
arr[1] = " ";
arr[2] = "world";
arr[3] = " ";
arr[4] = "!!";
String result = null;
for (String s : arr) {
result += s;
// new StringBuilder(String.valueOf(null).append("hello")
// new StringBuilder(String.valueOf("hello").append(" ")
// new StringBuilder(String.valueOf("hello ").append("world")
// new StringBuilder(String.valueOf("hello world ").append("!!")
}
StringBuffer
는 synchronized
가 적용되어 Multi-Thread환경에서 Thread-safe하게 동작
할 수 있습니다.
동기화를 지원하는 StringBuilder로 이해하시면 됩니다.
잘보고갑니다.