Immutable(불변성), StringBuffer와 StringBuilder

2024. 10. 29. 23:21·💻 Dev/Java & OOP
String str = "Hello";
System.out.println("String 객체의 주소 : "+str.hashCode());
str = str + " World";
System.out.println("String 객체의 주소 : "+str.hashCode());

 

리터럴로 선언한 문자열 객체의 주소를 출력하고, 문자열만 더한 다음 객체 주소를 다시 출력해 보는 코드이다.

 

다시 변수를 만든 것도 아닌데 주소가 같지 않을까?

String 객체의 주소 : 3541040
String 객체의 주소 : 1758230625

하지만 아니다.

 

왜일까?
자바에서 String 객체는 기존 객체를 재사용하지 않는다, 같은 객체에 더한다고 해도 새로운 객체가 생성되고 기존 객체는 GC의 대상이 된다.
즉, String 클래스는 Immutable, 불변성을 갖는다.

 

그래서 변경이 자주 일어나는 프로그램에서 String만 사용하게 되면 효율적인 성능을 기대하기 어렵다.

 

이 단점을 보완하기 위해 나온 클래스가 StringBuffer와 StringBuilder다.

 

StringBuffer와 StringBuilder

public final class StringBuffer  
   extends AbstractStringBuilder  
   implements Serializable, Comparable<StringBuffer>, CharSequence

public final class StringBuilder  
    extends AbstractStringBuilder  
    implements java.io.Serializable, Comparable<StringBuilder>, CharSequence

 

StringBuffer와 StringBuilder 두 클래스 모두 AbstractStringBuilder 라는 추상 클래스를 상속받고 있다.

 

 

AbstractStringBuilder 추상 클래스의 멤버 변수엔 2가지 변수가 존재한다.

byte[] value; //The value is used for character storage.
int count; //The count is the number of characters used.

 

두 클래스 모두 문자열을 수정할 때 append() 메서드를 사용한다.

public AbstractStringBuilder append(String str) {  
    if (str == null) {  
        return appendNull();  
    }  
    int len = str.length();  
    ensureCapacityInternal(count + len);  
    putStringAt(count, str);  
    count += len;  
    return this;}

문자열을 추가하게 되면 추가할 문자열의 크기(길이)만큼 현재의 문자열을 저장하는 배열의 크기를 늘려주고,

그 공간에 문자열을 넣어주는 방식이다.

 

즉, 같은 주소공간을 참조하며 값이 변경되기 때문에 두 클래스는 Muttable, 가변성을 가진다.

 

이 두 클래스에서도 차이점이 존재하는데 바로 동기화(Synchronization)이다.

@Override  
@HotSpotIntrinsicCandidate  
public synchronized StringBuffer append(String str) {  
    toStringCache = null;  
    super.append(str);  
    return this;}

StringBuffer는 메서드에서 synchronized 키워드를 사용하기 때문이다.


synchronized 키워드는 자바에서 동기화를 구현하는 키워드로, synchronized 블록을 사용하고 있는 스레드 외에 다른 스레드가 접근할 수 없도록 차단하는 것이다.

 

즉, 여러 스레드의 동시 접근을 막아 멀티스레드 환경에서 데이터의 일관성을 보장할 수 있다.

 

StringBuilder는 동기화가 없어 멀티스레드 환경에서 안전하지 않지만, 그로 인한 성능 저하가 없어 단일 스레드에서 더 빠르다.

 

 

문자열의 추가, 수정, 삭제 등 변경이 빈번한 경우 각각 언제 사용하는 게 좋을까?

  • StringBuffer - 멀티스레드 환경
  • StringBuilder - 단일스레드 환경

 

 

참고

StringBuilder와 StringBuffer는 무슨 차이가 있는가?

저작자표시 비영리 (새창열림)

'💻 Dev > Java & OOP' 카테고리의 다른 글

자바는 Call by Value만 사용한다.  (0) 2024.11.22
String Constant Pool, feat. Runtime Constant Pool  (0) 2024.11.02
BigDecimal이란?  (0) 2024.10.30
자바 코드의 메모리 영역(스택&힙)  (0) 2024.10.29
JVM 구조와 동작 과정  (0) 2024.10.29
예외(Checked Exception, Unchecked Exception)  (0) 2024.10.26
'💻 Dev/Java & OOP' 카테고리의 다른 글
  • String Constant Pool, feat. Runtime Constant Pool
  • BigDecimal이란?
  • 자바 코드의 메모리 영역(스택&힙)
  • JVM 구조와 동작 과정
현주먹
현주먹
끄적끄적 개발.log
  • 현주먹
    현주먹의 개발로그
    현주먹
  • 전체
    오늘
    어제
    • 전체글 (162)
      • 👶🏻 CS (15)
        • Operating System (8)
        • Database (4)
        • Data Structure (2)
        • Software Engineering (1)
      • 💻 Dev (54)
        • Java & OOP (24)
        • Spring (4)
        • JPA (5)
        • Test Code (1)
        • Database (1)
        • JSP & Servlet (13)
        • Etc (6)
      • 💡 Algorithm (25)
        • 인프런 (9)
        • 백준 (16)
      • 🛠 DevOps & Tool (11)
        • Linux (4)
        • AWS (1)
        • Git (2)
        • Etc (4)
      • 📝 끄적끄적 (57)
        • 후기 및 회고 (5)
        • TDD, 클린 코드 with Java 17기 (3)
        • F-Lab (23)
        • 🖥️ 자바의 정석 (11)
        • 📖 Clean Code (3)
        • 항해99 코테 스터디 (11)
  • 블로그 메뉴

    • 🐈‍⬛ GitHub
    • TIL
  • 인기 글

  • 태그

    TDD 클린 코드 with Java
    데브클럽
    자바의정석
    항해99
    인프런 단어뒤집기
    JPA
    티스토리챌린지
    코딩테스트준비
    자바의신절판
    NextSTEP
    개발자멘토링
    오블완
    코테스터디
    객체지향
    f-lab 후기
    PostGreSQL함수
    til
    ==와 equals()
    99클럽
    에프랩
    개발자취업
    오라클
    F-Lab
    백준
    로또 미션
    C
    jsp
    에프랩 후기
    백준10250
    인프런 특정문자뒤집기
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
현주먹
Immutable(불변성), StringBuffer와 StringBuilder
상단으로

티스토리툴바