[Java] String, StringBuffer, StringBuilder

2022. 10. 22. 17:10TIL💡/Java

분류 String StringBuffer StringBuilder
변경 Immutable Mutable Mutable
동기화 Thread-safe Synchronized 가능(Thread-Safe) Synchronized 불가능
저장 Heap & Stack에서 참조 Buffer → toString() 시에 메모리 할당

1. String 특징

  • new 연산을 통해 생성된 인스턴스의 메모리 공간은 변하지 않음 (Immutable)
  • Garbage Collector로 제거되어야 함
  • 문자열 연산 시 새로 객체를 만드는 Overhead 발생
  • 객체가 불변하므로, Multihead에서 동기화를 신경 쓸 필요가 없다.

→ 문자열 연산이 적고, 조회가 많은 멀티 쓰레드 환경에 좋음

문자열 추가,수정,삭제 등의 연산이 빈번하게 발생하는 알고리즘에 String 클래스를 사용하면 힙 메모리(Heap)에 많은 임시 가비지(Garbage)가 생성되어 힙메모리가 부족으로 어플리케이션 성능에 치명적인 영향을 끼치게 된다.

그런데 매번 String이 heap에 저장되는 것은 아니다.

 

String 객체는 new를 통해 만드는 것을 추천하지 않는다.

그렇게 만들면 매번 새로운 객체가 생성되어 각각 Heap 영역을 차지하기 때문이다.

Heap 중에서도 String pool이라는 특정한 영역에 저장된다. String 의 캐시값을 key로 두어 해시테이블 형식으로 효율적으로 String을 관리한다.

원래 자바 6이전에는 Spring Pool은 사실 Heap 메모리에 존재하지 않았다. 바로 PermGen에 위치했다.

따라서 너무 많은 String 데이터를 사용하지 않을 경우 OOM이 일어나기 쉬웟다.

Java 7로 올라오면서 String Pool은 PermGen이 아닌 Heap 메모리 영역으로 위치를 옮겼다.

Java 8이 되면서 고정크기로 많은 문제를 일으켰던 PermGen은 Metaspace로 이름을 변경하였고, 동적크기로 변화하여 메모리 구성이 변경되었다.

 

예시)

class Testimmutablestring{  
 public static void main(String args[]){  
   String s="Sachin";  
   s.concat(" Tendulkar");//concat() method appends the string at the end  
   System.out.println(s);//will print Sachin because strings are immutable objects  
 }  
}
class Testimmutablestring1{  
 public static void main(String args[]){  
   String s="Sachin";  
   s=s.concat(" Tendulkar");
   System.out.println(s);  // output: Sachin Tendulkar
 }  
}

 

2. StringBuffer, StringBuilder 특징

공통점

  • new 연산으로 클래스를 한 번만 만든다.(Mutable)
  • 문자열 연산 시 새로 객체를 만들지 않고, 크기를 변경시킨다.
  • StringBuffer와 StringBulder 클래스의 메서드가 동일하다.

차이점

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

→ StringBuffer 클래스: 문자열 연산이 많은 Multi-Thread 환경

→ StringBuilder 클래스: 문자열 연산이 많은 Single-Thread

 

 

참고

- https://conservative-vector.tistory.com/entry/Java-String-String-buffer-String-builder