본문 바로가기
Java

String, StringBuffer, StringBuilder

by seonggu 2024. 2. 26.

String, StringBuffer, StringBuilder

  1. String 특징
    new 연산을 통해 생성된 인스턴스의 메모리 공간은 변하지 않음 (Immutable)
    Garbage Collector로 제거되어야 함
    문자열 연산시 새로 객체를 만드는 OverHead 발생
    객체가 불변하므로, Multithread에서 동기화를 신경쓸 필요가 없음 (조회 연산에 매우 큰 장점)

String 클래스 : 문자열 연산이 적고, 조회가 많은 멀티쓰레드 환경에서 좋음

  1. StringBuffer, StringBuilder 특징

-공통점
new 연산으로 클래스를 한 번만 만듬(Mutable)
문자열 연산시 새로 객체를 만들지 않고, 크기를 변경시킴
StringBuffer와 StringBuilder 클래스의 메서드가 동일함


-차이점
StringBuffer는 Thread-Safe함 / StringBuilder는 Thread-safe하지 않음(불가능)

StringBuffer클래스 : 문자열 연산이 많은 Multi-Thread 환경
StringBuilder클래스 : 문자열 연산이 많은 Single-Thread 또는 Thread 신경 안쓰는 환경


위에서 String은 immutable(불변)하며, StringBuilder는 Mutable(가변)한다고 했음
예시를 통해서 알아보자.



  • String 클래스의 객체는 생성된 후에 변경할 수 없다. 문자열을 수정하려면 새로운 문자열 객체가 생성된다.
    String str = "Hello";  
    str = str + " World"; //새로운 문자열이 생성되고 str은 변경되지 않음   
    이러한 불변성은 스레드 안정성과 부작용을 방지하는 데 도움됨.

  • StringBuilder 클래스는 문자열을 변경할 수 있는 가변 객체이다. 기존 객체를 수정하고 새로운 객체를 생성하지 않는다.
    Stringbuilder sb = new StringBuilder("Hello");  
    sb.append(" World"); // 동일한 객체를 수정함  
    가변성으로 인해 문자열을 빈번하게 수정해야할 경우 StringBuilder를 사용하는 것이 성능상 이점이 있을 수 있음.

문자열이 자주 수정되지 않고 불변해야 하는 경우 String을 사용하고, 문자열이 동적으로 자주 변경되어야 하는 경우 StringBuilder 사용하는 것이 좋다.


불변성(Immutabilty)은 여러 면에서 스레드 안정성 및 부작용 방지에 도움을 준다.



1) 스레드 안정성(Thread Safety) : 여러 스레드에서 동시에 데이터를 수정하는 경우, 데이터의 무결성이 깨질 수 있다. 불변 객체는 수정이 불가능하므로 여러 스레드가 동시에 객체에 접근해도 안전하다. 따라서 불변성은 스레드 안정성을 쉽게 달정할 수 있도록 도와준다.
2) 부작용 방지 : 불변 객체는 생성된 후에 내부 상태가 변경되지 않는다. 이로 인해 예측이 가능하며 안정된 동작을 제공합니다. 부작용(원치 않은 상태 변경)을 방지하고 코드의 복잡성을 줄이는 데 도움된다. 부작용이 없으면 코드를 이해하고 디버그하기 더 쉽다.
3) 캐싱 및 재사용 : 불면 객체는 한 번 생성되면 변하지 않으므로 동일한 값을 여러번 사용하거나 캐싱하는 데 적합하다. 동일한 값에 대한 여러 객체를 생성하지 않고 이미 생성된 객체를 공유함으로써 메모리 사용을 최적화 할 수 있다.
4) 함수형 프로그래밍 지원 : 불변성은 함수형 프로그래밍의 핵심 개념 중 하나이다. 함수형 프로그래밍에서는 부작용을 피하고 상태를 변경하지 않는 함수를 선호한다. 불변 객체는 이러한 개념을 자연스럽게 지원하며, 함수형 스타일의 코드 작성을 촉진한다.


public class ImmutableExample {  
    private final int value;  

    public ImmutableExample(int value) {  
        this.value = value;  
    }  

    public int getValue() {  
        return value;  
    }  

    public ImmutableExample add(int x) {  
        return new ImmutableExample(this.value + x);  
    }  

    public static void main(String\[\] args) {  
        ImmutableExample obj = new ImmutableExample(10);  

        // 불변 객체의 메서드를 호출하더라도 원본 객체는 변경되지 않음  
        ImmutableExample newObj = obj.add(5);  

        System.out.println(obj.getValue());  // 10  
        System.out.println(newObj.getValue());  // 15  
    }  
}