🐰 Java의 String과 SpringBuffer

Java의 String

  • java에서 String은 객체이다.
  • int, char와 달리 기본형,원시형(primitive type)이 아닌 참조형(reference type)변수로 분류된다.
  • 메모리의 Stack영역이 아닌, Heap영역에서 문자열 데이터가 생성되고 다뤄진다는 말이다. Pasted image 20250110122312.png
  • 또한 String은 불변(Immutable)객체이다.
    • 예를들어, s = "a"; 에 s = s + s; 를 하면 "aa"가 되겠지만, heap영역 메모리에 새로운 주소로 생성하게 된다.

왜 불변객체로 설계 되었을까?

1. 성능적 이득

  • JVM에서는 String Constant Pool이라는 독립적인 영억을 Heap영역에 구축하여 문자열들을 Constant화 하여 다른 변수 혹은 객체들과 공유한다.
  • 이 과정에서 데이터 캐싱이 일어나고, 그만큼 성능적인 이득을 취할 수 있게된다.

2. 안정성

  • 데이터가 불변하다면, 멀티 스레드 환경에서 동기화 문제가 발생하지 않기 때문에 안전한 결과를 낼 수 있다.

3. 보안

  • 만일 번지수의 문자열 값이 변경이 가능하다면, 참조값을 변경하여 애플리케이션에 보안 문제를 일으킬 수 있다.

Java에서 String 주소 할당방식

1. 문자열 리터럴을 이용한 방식 - String str1 = "안녕";

2. new연산 이용방식 - String str2 = new String("안녕");

둘다 "안녕" 이라는 문자열을 저장하는 점은 같지만, JVM 내부 메모리 측면에서는 큰 차이가 있다.

  • 먼저 문자열 리터럴 방식으로 변수에 저장하게 되면, 이 값은 string constant pool에 저장이 되지만, new연산자를 사용하여 생성한 값은 Heap영역에 존재하게된다.

비교 연산

equals

  • 대상 값 자체를 비교

==

  • 대상의 주소값을 비교.

즉, new연산자를 통해 만들어진 객체를 equals로 비교한다면 true가 나오겠지만, == 연산자를 사용한다면 false가 나오게 되는것이다.


SpringBuffer와 SpringBuilder

두 클래스 모두 문자열을 연산(추가 및 변경)할 때 주로 사용하는 자료형이다. 물론 String자료형 으로도 +concat()으로 문자열을 이어붙일수 있다. 하지만 +를 이용해 String인스턴스의 문자열을 결합하면, 내용이 합쳐진 새로운 String인스턴스를 생성하게된다. 문자열을 많이 결합하면 결합할수록 공간낭비는 물론, 속도 또한 매우 느려진다.

이를 해결하기 위해 Java는 문자열 연산을 전용으로 하는 자료형을 따로 만들어 제공하였다.

SpringBuffer란?

  • 내부적으로 Buffur라고 하는 독립적인 공간을 가지게 되어
  • 문자열을 바로 추가할 수 있어 공간의 낭비도 없으며, 문자열 연산 속도도 매우 빠르다

기본적으로 16개의 문자를 저장할 수 있는 크기이며, 연산 중 할당된 버퍼의 크기를 넘게되면 자동으로 버퍼를 증강 시킨다.

또한 다양한 내장 메서드를 지원하여, 문자열을 가공할 수 있다.

SpringBuffer와 SpringBuilder의 메서드 사용법은 동일하다.

String vs (SpringBuffer와 SpringBuilder)

String은 불변

  • 불변자료형 으로써, 초기 공간과 다른 값에 대해서 새로운 메모리 공간을 할당하여 새로 생성한다.
  • 그렇게 남겨진 문자열 값은 java가비지 컬렉터에 의해 제거될 대상에 포함된다.

SpringBuffer와 SpringBuilder는 가변

  • 즉, 문자열을 조작할 때 새 객체를 생서하지 않고 기존 객체를 수정한다.
  • 메모리 관리 측면에서 효율적
특성 String StringBuffer StringBuilder
가변성 불변 (Immutable) 가변 (Mutable) 가변 (Mutable)
스레드 안전성 스레드 안전 스레드 안전 스레드 안전하지 않음
속도 상대적으로 느림 상대적으로 느림 (동기화로 인한) 빠름 (동기화 없음)
주요 사용 사례 읽기 전용 데이터 처리 멀티스레드 환경에서 문자열 조작 단일 스레드 환경에서 문자열 조작

그렇다면 문자열 + 연산시에는 무조건 String을 사용하는것이 옳지 않은건가??

=> 사실 자바는 문자열에 + 연산을 사용하면, 컴파일 전 내부적으로 StringBuilder 클래스를 자동으로 생성한 후 다시 문자열로 돌려준다. 다만, 문자열을 합치는 일이 빈번할 경우에는 단순히 +연산을 사용하는것은 효율이 떨어지므로 SpringBuffer와 SpringBuilde 를 사용하는것이 옳다고 할 수 있다.