// String 클래스에서 문자열을 저장하는 배열
private final byte[] value;
-> 'final' 키워드로 value 배열을 선언해서 값을 바꾸지 못한다.
문자열 비교는 equals(String str) 메소드를 사용한다.
== 연산자는 레퍼런스 비교(String 참조변수가 reference를 저장하기 때문)
String literal과 String Object는 조금 다른 특성이 있는데 String literal은 먼저 자세히 보자.
String literal은 String Constant Pool이라는 영역에서 다룬다. 한번 할당된 literal을 다른 참조변수가 reference하면 같은 literal을 reference한다.
String Object는 Heap영역에 할당되고, 생성자 호출시마다 Heap의 다른 영역에 할당된다.
위 차이는 아래 코드로 설명된다.
public class Main {
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true
System.out.println(s1==s3); //false
System.out.println(s1.equals(s3)); //true
}
}
String 추가자료 : String literal/Object를 인스턴스 변수로 갖는 Class의 인스턴스의 ==와 equals()를 잘 설명하는 글.
StringBuffer sb = new StringBuffer("Hello");
sb.append("w").append("orld"); // append()로 문자열을 덧붙일 수 있음.
** 위의 StringBuffer는 StringBuilder로 치환 가능(동일 API 지원)
주요 API
메소드 | 기능 | |
---|---|---|
append(Arg a) | String Buffer sequence 뒤에 a를 string representation형태로 덧붙임 | a는 primitive(byte, short제외), String, String Buffer, Object Class 등 가능 |
insert(int offset, Arg a) | a를 String Buffer의 offset 위치에 덧붙임 | |
replace(int start, int end, String str) | start, end가 지정하는 substring을 str로 대체 |
문자열 비교 : java.lang.Object의 equals()를 overriding 하지 않음. ==도 레퍼런스 비교.
-> toString()으로 String으로 변환하여 equals()로 비교한다.
차이점 : synchronized 지원 여부
StringBuffer는 synchronized 를 지원하여 멀티쓰레드 환경에서 thread-safe 하다.
** String은 immutable이라 마찬가지로 멀티쓰레드 환경에서 thread-safe 하다.
@Override
@IntrinsicCandidate
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
반대로 StringBuilder는 synchronized 를 지원하지 않기때문에 멀티쓰레드 환경에서 thread-unsafe이지만 동기화를 고려하지 않는 만큼 단일쓰레드에서의 성능은 StringBuffer 보다 좋다.
@Override
@IntrinsicCandidate
public StringBuilder append(String str) {
super.append(str);
return this;
}
append의 parameter로는 다양한 type이 가능하다(String과 마찬가지로 byte로 변환하여 저장하기 때문?)
StringBuffer buffer = new StringBuffer();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < 20000000; i++) {
buffer.append("Hello").append(" World").append(" Java").append(" Programming");
} // 903ms
for (int i = 0; i < 20000000; i++) {
builder.append("Hello").append(" World").append(" Java").append(" Programming");
} // 1064 ms
위 실험(2000만회 반복)결과 약 1.06초의 성능차를 확인했다.
append할 문자열이 길 수록, 반복이 많을 수록 그 차이가 많이 날 것이다.
String | StringBuffer | StringBuilder | |
---|---|---|---|
저장공간 | Constant String Pool | Heap | Heap |
변경 | 불가 | 가능 | 가능 |
Thread-safe(Synchronized) | O | O | X |
성능 | 빠름 | 느림 | 빠름 |