개발/Java

String, StringBuilder, StringBuffer

Debin 2022. 3. 1.
반응형

String 클래스에는 문자열을 저장하기 위해서 문자열 배열 참조 변수를 인스턴스 변수로 정의해놓고 있다.

인스턴스 생성 시 생성자의 매개변수로 입력받는 문자열은 이 인스턴스 변수에 문자형 배열에 저장되는 것이다.

String VS StringBuilder, StringBuffer 차이

String 인스턴스가 갖고 있는 문자열은 읽어 올 수만 읽고, 변경할 수는 없다. 불변이다. (immutable)

StringBuilfer, StringBuffer는 각각의 인스턴스에 저장된 문자열 변경이 가능하다. 가변적이다. (mutable)

 

즉 아래와 같이 '+'연산자를 이용해서 문자열을 결합하는 경우 인스턴스 내의 문자열이 바뀌는 것이 아니라

새로운 문자열 "ab"이 담긴 String 인스턴스가 생성되는 것이다.

String a = "a";

String b = "b";
a = a + b;

즉 아래 그림처럼 덧셈 연산자 '+'를 사용해서 문자열을 결합하는 것은

매 연산 시마다 새로운 문자열을 가진 String인스턴스가 생성되어 메모리 공간을 차지하게 되므로 가능한 한 결합 횟수를 줄이는 것이 좋다.

 

아래처럼 a는 새로운 메모리를 가리키고 기존에 a는 가비지 콜렉터에 의해 수거된다.

문자열 연산 시 메모리 모습

반대로 StringBuffer과 StringBuilder를 살펴보자.

StringBuffer sb = new StringBuffer("a");
sb.append("b");

StringBuffer, StringBuilder은 가변적이기 때문에 아래 이미지와 같이 동작한다.

StringBuffer, StringBuilder 사용 시 메모리 모양

 

문자열의 비교

문자열을 만들 때는 두 가지 방법, 문자열 리터럴을 지정하는 방법과 String클래스의 생성자를 사용해서 만드는 방법이 있다.

아래와 같은 코드를 살펴보자.

String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");

String 클래스의 생성자를 이용한 경우에는 new 연산자에 의해서 메모리 할당이 이루어지기 때문에

항상 새로운 String 인스턴스가 생성된다.

그러나 문자열 리터럴은 이미 존재하는 것을 재사용하는 것이다.

 

 문자열 리터럴은 클래스가 메모리에 로드될 때 자동적으로 미리 생성된다.

 

위 코드가 실행될 때 상황

자바 소스파일에 포함된 모든 문자열 리터럴은 컴파일 시에 클래스 파일에 저장된다.

이때 같은 내용의 문자열 리터럴은 한 번에 저장된다.

문자열 리터럴도 String 인스턴스이고, 한번 생성하면 내용을 변경할 수 없으니 하나의 인스턴스를 공유하면 되기 때문이다.

클래스 파일에는 소스파일에 포함된 모든 리터럴의 목록이 있다. 

해당 클래스 파일이 클래스 로더에 의해 메모리에 올라갈 때, 이 리터럴의 목록에 있는 리터럴들이,

JVM내에 있는 '상수 저장소' (Constant Pool)에 저장된다.

 

이때, 이곳에 'abc'와 같은 문자열 리터럴이 자동적으로 생성되어 저장되는 것이다.

StringBuilder, StringBuffer 차이

StringBuilder과 StringBuffer은 문자열을 다루며 가변적이다.

또한 제공되는 API(메서드)도 동일하다.

 

그러면 이 둘의 차이점은 무엇일까?

StirngBuffer는 멀티스레드에 안전하도록 동기화되어 있다.

동기화가 StringBuffer의 성능을 떨어뜨릴 수 있다.

멀티스레드로 작성된 프로그램이 아닌 경우, StringBuffer의 동기화는 불필요하게 성능만 떨어뜨린다.

 

그래서 StringBuilder이 등장했다. StringBuilder는 StringBuffer의 기능에서 스레드의 동기화만 뺀 것이다.

동기화를 지원하지 않으니 당연히 멀티쓰레드 환경에서 안전하지 않다. 

따라서 멀티스레드 환경을 고려하면 StringBuffer을 사용하고 단일 스레드 환경에서는 StringBuilder을 사용하면 되겠다.

 

전체적인 차이는 아래 표와 같이 정리할 수 있다.

 

String, StringBuilder, StringBuffer 차이점

String도 불변 객체이므로 멀티 환경 스레드에서 안전하다.

 

 

 

참고 자료

자바의 정석

https://tuandevnotes.com/string-vs-stringbuffer-vs-stringbuilder/

반응형

댓글