💡 불변 객체로, 문자열 상수 풀에서 동일한 값을 가진 문자열 객체의 참조를 만들거나 반환한다. String 클래스의 생성자를 사용하면 새 문자열을 만든다.
// java
String str = "ABC";
String str = new String("ABC");
// kotlin
val str: String = "ABC"
val str: String = String("ABC")
✅ 문자열 풀 : 힙 메모리 영역 안에 위치하는 메모리 영역으로, 리터럴로 생성한 문자열을 저장하여 중복을 방지하고 메모리를 효율적으로 사용할 수 있습니다.
new 연산자를 사용하여 문자열을 생성하면 힙 메모리에 생성된다.
+ 연산자는 문자열에 대해 오버로드된다. 이를 사용하여 두 문자열을 연결할 수 있다. 내부적으로는 StringBuilder를 사용하여 이 작업을 수행한다.
String은 equals() 및 hashCode() 메서드를 재정의한다. 두 문자열은 동일한 문자 순서를 갖는 경우에만 동일하다. equals() 메소드는 대소문자를 구분한다. 대소문자를 구분하지 않는 검사를 찾고 있다면 equalsIgnoreCase() 메소드를 사용해야 한다.
문자열은 문자 스트림에 UTF-16 인코딩을 사용한다.
문자열은 final 클래스이다. private int hash
를 제어한 모든 필드는 final 필드이다. 이 필드는 hashCode() 함수 값이 포함되어 있다. 해시코드 값은 hashCode() 메서드가 처음 호출된 후 이 필드에 저장되는 경우에만 계산된다. 또한, 일부 계산과 함께 String 클래스의 final 필드를 사용하여 해시가 생성된다.
💡 StringBuilder : 가변 객체로 문자열 조작을 위한 메소드를 제공하며, 멀티스레드 환경에서 가변 객체는 동시접근이 가능하여 안전하기 않기 때문에 단일스레드 환경에서 주로 사용한다.
💡 StringBuffer : 가변 객체로 문자열 조작을 위한 메소드를 제공하며, 멀티스레드 환경에서 스레드 동기화를 제공하여 안전하지만, 성능 비용이 발생해 StringBuilder보다 느릴 수 있다.
가변 객체로서 문자열 조작을 위한 메소드를 제공한다. 멀티스레드 환경에서 가변 객체는 동시접근이 가능하여 안전하기 않기 때문에 멀티스레드 환경에서는 스레드로부터 안전한 작업을 위해 StringBuffer를 사용해야한다.
import java.util.GregorianCalendar;
public class TestString {
public static void main(String[] args) {
System.gc();
long start = new GregorianCalendar().getTimeInMillis();
long startMemory = Runtime.getRuntime().freeMemory();
StringBuffer sb = new StringBuffer();
//StringBuilder sb = new StringBuilder();
for(int i = 0; i < 10000000; i++){
sb.append(":").append(i);
}
long end = new GregorianCalendar().getTimeInMillis();
long endMemory = Runtime.getRuntime().freeMemory();
System.out.println("Time Taken:" + (end - start));
System.out.println("Memory used:" + (startMemory - endMemory));
}
}
i의 값 | StringBuffer (Time, Memory) | StringBuilder (Time, Memory) |
---|---|---|
10,00,000 | 808,149356704 | 633,149356704 |
1,00,00,000 | 7448,147783888 | 6179,147783888 |
- String은 변경할 수 없지만 StringBuffer 및 StringBuilder는 변경 가능한 클래스이다
- StringBuffer는 스레드로부터 안전하고 동기화되지만 StringBuilder는 그렇지 않다. 이것이 StringBuilder가 StringBuffer보다 빠른 이유다.
- 문자열 연결 연산자(+)는 내부적으로 StringBuffer 또는 StringBuilder 클래스를 사용한다.
- 멀티 스레드가 아닌 환경에서 문자열을 조작하려면 StringBuilder를 사용해야 하며 그렇지 않으면 StringBuffer 클래스를 사용해야 한다.