[Java] String, StringBuffer, StringBuilder

Ahnick·2021년 2월 13일
0
post-thumbnail

String Class

자바에서는 문자열을 표현하는 String Class가 있습니다.
String Class는 자바에서 조금 특별한 Class이며 마치 사용 빈도가 굉장히
높기 때문에 마치 기본 타입처럼 특수한 선언이 가능하지만, Heap 영역에서
사용되는 참조형 클래스입니다.

String Class는 '+' 연산자 그리고 append() 메소드 등 마치 객체 값 자체를
바꿀 수 있는 메소드처럼 보이는게 존재하지만 String은 immutable한
'불변' 객체입니다.
실제로 자바 공식 문서에는 String이 constant라고
정의되어 있습니다.

따라서, '+'연산자, append 등으로 String의 형태를 변형하면
String 객체의 값이 바뀌는게 아니라 해당 형태를 가진 새로운 String 객체를
생성한 뒤, 해당 변수가 새롭게 생성된 객체의 주소
를 가리키게 됩니다.

그리고 자신을 가리키는 변수가 없어진 기존의 String은 GC(Garbage Collector)에
의해서 제거되는데
, 만약 이러한 String 연산의 반복이 무수히 많이 이루어지는
환경이라면 GC의 빈번한 동작이 성능 저하의 주요 원인이 됩니다 !

String Pool

위에서 언급했듯이, String은 자바에서 조금 특별한 클래스입니다.
참조 타입은 동일한 필드를 주고 객체를 생성해도 ==으로 비교가 불가능하다고
알려져 있습니다. 그럼 다음 경우는 어떨까요?


일반적인 상식과는 다르게, true 결과가 나왔습니다. String은 분명 참조타입인데
어째서 이런 결과가 나올까요? 그럼 이번엔 다음 코드로 테스트를 해보겠습니다.

hashCode() 메소드는 해당 객체의 주소값을 16진수 코드로 변환해서 보여줍니다
두 객체는 다른 주소값을 가질까요?

결과를 보면 알 수 있듯이, 우리가 별개로 선언했던 두 String 객체가 동일한 주소를 가지고 있는걸
볼 수 있습니다. 자바에서는 String을 위한 String Pool이라는, 마치 캐시와 같은 개념이 존재합니다.

따라서 immutable한 String을 위해서 자바는 Heap 영역에 String Pool을 생성하고 여기에서
String들을 관리합니다. 그리고 우리는 intern()이라는 메소드를 통해서 String들을 이곳에 할당할 수 있지만
인위적으로 intern을 남발하여 String Pool을 비대하게 늘린다면 어플리케이션의 심각한 성능저하가
유발되기 때문에 intern과 String Pool은 신중하게 접근해야 합니다
.

StringBuffer & StringBuilder Class

StringBuffer와 StringBuilder는 모두 String의 immutable한 특성을 보완하기 위해 고려된
Class입니다. StringBuffer와 StringBuilder는 모두 mutable한 특성을 가지는데,
append와 같은 연산을 수행해도 동일한 객체에서 작동합니다.

따라서 우리가 String을 수정하는일이 빈번하고, String의 내용이 수정이 계속된다면
성능상으로 StringBuffer 또는 StringBuilder를 사용하는게 유리합니다!

StringBuffer vs StringBuilder

그렇다면 StringBuffer와 StringBuilder는 어떠한 차이가 있고, 둘의 사용 목적은 어떤식으로 다르기에
이렇게 두 개의 클래스로 구분하여 구현한 걸까요?

두 클래스의 가장 큰 차이점은 'Thread Sync'입니다. StringBuffer는 쓰레드간 동기화를 지원합니다.
만약 어떠한 문자열이 존재하고 여러 개의 쓰레드가 이 문자열에 동시에 접근하여 작업을 수행해야한다면
멀티쓰레드 환경에서 안전성을 보장하며 쓰레드간 싱크를 보장하는 StringBuffer를 사용해야합니다.

하지만 String을 단일 메소드에서만 사용한다면 성능상으로 유리한 StringBuilder를 사용하는게
유리합니다!

String, StringBuffer, StringBuilder 정리

StringStringBufferStringBuilder
가용 영역String PoolHeapHeap
수정 여부ImmutableMutableMutable
Thread SafeYes (Constant)YesNo
Thread SyncYes (Constant)YesNo
성능FastSlowFast

각 String 연관 Class를 정리하면 위의 표와 같은 결과가 나옵니다. 만약 우리가
어떠한 문자열을 처리해야하고 위의 세 개중 어떤 Class를 사용할지 미정 상태일 경우,
위 세 개의 클래스 공통조상인 CharSequence를 통해 입력을 받는 방법이 있습니다.

만약 어떠한 Application 환경을 운영한다면, String의 빈번한 수정이 발생하므로
Thread를 고려하여 StringBuffer/StringBuilder를 사용하여 Application의 성능을
보장하도록 할 것 같습니다.

0개의 댓글