StringBuilder Vs StringBuffer

oh_eol·2024년 1월 4일
0

Java Study

목록 보기
1/3
post-thumbnail

Java 에서 String 클래스는 불변성을 갖는다. 그래서 문자열이 변하지 않는 경우에는 좋은 성능을 기대할 수 있다.
그럼 문자열에 대한 변경이 자주 일어날 경우에는 어떻게 하나? 바로 StringBuilder, StringBuffer 를 사용한다.
이 셋에 어떤 차이가 있고 언제 써야 하는지, 다음 목차에 따라서 알아보자.

  • String VS StringBuilder/StringBuffer
  • StringBuilder VS StringBuffer
  • String을 사용해야 할 때
  • StringBuilder를 사용해야 할 때
  • StringBuffer를 사용해야 할 때

1. String VS StringBuilder/StringBuffer

Java에서 String 객체는 한 번 값이 할당되면 그 공간은 변하지 않는다. 하지만 StringBuilderStringBuffer 객체는 한 번 값이 할당되더라도 한 번 더 다른 값이 할당되면 할당된 공간이 변하는 특성을 갖고 있다. 즉,

  • String : 불변성을 갖는다.(다른 값을 할당하려면 새로 할당해야 한다.)
  • StringBuilder, StringBuffer : 가변성을 갖는다.(새로 할당되는 값에 맞추어 공간이 변한다.)

예시 코드

        String str = "strA";
        StringBuilder sbd = new StringBuilder();
        StringBuffer sbf = new StringBuffer();

        sbd.append("sbdA");
        sbf.append("sbfA");

        System.out.println("String 객체의 주소 : " + str.hashCode());
        System.out.println("StringBuilder 객체의 주소 : " + sbd.hashCode());
        System.out.println("StringBuffer 객체의 주소 : " + sbf.hashCode());

        str += "strB";
        sbd.append("sbdB");
        sbf.append("sbfB");
        System.out.println("==========================");

        System.out.println("String 객체의 주소 : " + str.hashCode());
        System.out.println("StringBuilder 객체의 주소 : " + sbd.hashCode());
        System.out.println("StringBuffer 객체의 주소 : " + sbf.hashCode());

String, StringBuilder, StringBuffer 타입의 변수를 선언하고 문자열을 수정하기 전에 객체의 주소를 해싱하여 값을 반환해주는 hashCode()의 반환 값을 출력하고, 문자열을 수정한 뒤 hashCode()의 반환값을 출력해보았다.

String 객체의 주소 : 3541040
StringBuilder 객체의 주소 : 1468177767
StringBuffer 객체의 주소 : 434091818
==========================
String 객체의 주소 : 1758230625
StringBuilder 객체의 주소 : 1468177767
StringBuffer 객체의 주소 : 434091818

위와 같이 String의 객체 주소만 바뀐 것을 확인할 수 있다.

  • String은 어디에 있는 메모리를 참조하여 값을 갖고 있을까?
  • String 객체의 값이 변할 때마다 어떻게 동작할까?

1-1. String Constant Pool

String 변수에 값을 할당하는 방법은 두 가지가 있다.

  • 리터럴 변수를 대입하는 방법
  • new 키워드를 사용하는 방법

위 두 가지 방법을 사용하여 예시코드를 작성해보자.

        String strA = "abc";
        String strB = new String("abc");
        String strC = "abc";
        String strD = new String("abc");

        System.out.println(strA == strB); // false
        System.out.println(strA == strC); // true
        System.out.println(strB == strD); // false

3개의 변수 모두 "abc"라는 문자열을 갖지만 주소비교(==)의 결과는 상이하다.
String 타입 값 할당 방식에 따른 저장 방식이 다르기 때문!

리터럴 값으로 값을 할당하는 경우
String을 리터럴 값으로 할당하는 경우엔 Heap 메모리 영역 안의 특별한 메모리 공간인 String constant pool 에 저장된다.
만약 String constant pool에 존재하는 리터럴 값을 사용하게 된다면 새롭게 리터럴 값을 만들어 String constant pool에 저장하는 것이 아니라 현재 존재하는 값을 사용하게 된다.
그래서 strA==strC 의 실행 결과가 true 로 나오는 것이다.

new 키워드로 값을 할당하는 경우
new 키워드를 통해 Stirng 변수에 값을 할당하게 되면 일반적인 객체와 동일하게 Heap 영역에 동적으로 메모리 공간이 할당되게 된다.
마찬가지로 같은 문자열이더라도 new 키워드로 한 번 더 할당하는 경우 다른 메모리 공간(Heap 영역 안)을 참조하게 된다.
그래서 strB==strD 의 실행 결과가 false 로 나오는 것이다.
strA==strB 의 실행결과가 false 로 나오는 경우도 서로 상이한 메모리 공간을 참조하기 때문!


2. StringBuilder VS StringBuffer

가변성을 갖는 두 객체는 모두 AbstractStringBuilder 라는 추상 클래스를 상속받아 구현되어 있다.
AbstractStringBuilder 추상클래스의 멤버 변수에는 다음 두 가지 변수가 존재한다.

  • value : 문자열의 값을 저장하는 byte형 배열
  • count : 현재 문자열 크기의 값을 가지는 int형 변수

StringBuilder와 StringBuffer 클래스의 문자열을 수정하고 싶은 경우 append() 메서드를 사용하게 되는데, 이는 StringBuilder, StringBuffer에 문자열을 추가할 경우 문자열의 크기만큼 현재의 문자열을 저장하는 배열의 공간을 늘려주고, 늘려준 공간에 추가할 문자열을 넣어주는 방식으로 되어있다.
따라서 값이 변경되더라도 같은 주소 공간을 참조하게 되는 것이며, 값이 변경되는 가변성을 띄게 되는 것이다.

그렇다면 둘의 차이점은? 바로 동기화(Synchronization)!
StringBuilder는 동기화를 지원하지 않는 반면, StringBuffer는 동기화를 지원하여 멀티 스레드 환경에서도 안전하게 동작할 수 있다.


3. String을 사용해야 할 때

위에서 "String은 불변성을 갖는다" 라는 사실을 배웠다.
그렇기 때문에 변하지 않는 문자열을 자주 사용할 경우 String 타입을 사용하는 것이 성능면에서 유리할 것이다.


4. StringBuilder를 사용해야 할 때

StringBuilder는 동기화를 지원하지 않는 반면, 속도 면에서는 StringBuffer보다 성능이 좋다.
그렇기 때문에 단일 스레드 환경문자열의 추가, 수정, 삭제 등이 빈번히 발생하는 경우 StringBuilder를 사용하는 것이 성능 면에서 유리할 것이다.


5. StringBuffer를 사용해야 할 때

StringBuffer는 동기화를 지원하여 멀티 스레드 환경에서도 안전하게 동작할 수 있다.
그렇기 때문에 멀티 스레드 환경문자열의 추가, 수정, 삭제 등이 빈번히 발생하는 경우 StringBuffer를 사용하는 것이 성능 면에서 유리할 것이다.


** 아래의 블로그를 참고하였습니다.
StringBuilder와 StringBuffer는 무슨 차이가 있는가?

profile
공부 중입니다.

0개의 댓글