@markdown


![String, StringBuffer, StringBuilder](https://t1.daumcdn.net/cfile/tistory/2412624F596CC78A31)

_

# String, StringBuffer, StringBuilder

_

## String 객체란?

### 사용법

_

```

String aString = "A String";

String bString = new String("B String");

```

_

문자열로 바로 초기화 해도되고 String 생성자를 이용해도 된다.

문자열끼리 더하거나 자를시에 String 의 `+` 연산자나 split() 등의 메소드를 사용하면 된다.

_

### 생성원리

String 객체는 생성시 문자열을 char[] 형태로 메모리에 할당시킨다.

그런데 이 객체는 길이가 정해진 배열이기 때문에 문자열을 더하거나 수정하는 경우 새로 객체를 생성, 할당하게 된다.

_

[주소 A, 원본문자열] => String 객체의 문자열

_

문자열 수정시

_

[주소 A, 원본문자열] // 버려짐

[주소 B, 수정문자열] => String 객체의 문자열

_

### 성능 문제

이렇게 String `+` 와 같은 연산시 객체가 계속 생성될 뿐만아니라 쓸모없는 문자열이 메모리에 남아 사용중인 메모리가 늘어나게 된다.

`+` 뿐만 아니라 모든 문자열 관련 메소드들도 마찬가지이다.

_

### StringBuffer 란?

String 의 그러한 점을 보완할 수 있는 것이 StringBuffer 이다.

StringBuffer 는 문자열을 내부적으로 관리할때 String 과 마찬가지로 char[] 로 담게 되는데 가변적으로 관리된다고 한다.

때문에 문자열 수정시 한 주소내에서 관리할 수 있다.

_

[주소 A, 원본문자열] => String 객체의 문자열

_

문자열 수정시

_

[주소 A, 수정문자열] => String 객체의 문자열

_

### Mutable, Immutable

번역하자면 `변하기 쉬운, 변하지 않는` 으로 해석할 수 있다. 

_

- String 객체는 Immutable 객체다. 길이가 고정되어 있어 변하지 않는다.

- StringBuffer 객체는 Mutable 객체다. 길이가 가변적으로 관리되어 늘어나거나 줄어들 수 있다.

_

문자열 관리적인 측면으로 보자면 위와같이 문자열 변경시 StringBuffer 객체가 유리하다. 그러나 결국 마지막에 문자열을 넣거나 사용하기 위해서 String 객체로의 변환이 필요하다. 

_

그러므로 변하지 않는 문자열의 경우 String 으로 관리하면 되고 변하게 되는경우 StringBuffer, StringBuilder 를 사용하면 된다.

_

## StringBuilder 란?

그렇다면 StringBuilder 는 무엇일까?

_

### JDK 1.5

JDK 1.5 에서 추가된 클래스로 StringBuffer 와 동작하는 방식은 모두 똑같다.

둘의 차이는 syncronized 이냐 아니냐로 구분되는데 thread safe 한 작업은 StringBuffer를 사용하고, 대부분의 경우에선 StringBuilder를 사용하도록 하자.

_

### 사용법

```

StringBuilder builder = new StringBuilder("초기값");


for (int i=0; i<10; i++) {

builder.append(", 추가값");

}


```

_

builder 객체를 생성하여 문자열 연산이 필요한 경우 append, insert 등을 이용하여 추가하면된다.

(자세한 설명은 생략)

_

## String 과 StringBuilder 차이

### 속도

String 의 `+` 연산과 StringBuilder 의 append() 속도차이를 보자

_

먼저 String 이다.

![String 속도 테스트](https://t1.daumcdn.net/cfile/tistory/23030433596CCAB217)

_

위 테스트에서 10000회 반복시 `+` 연산에서 738 밀리초가 소요되었다. 

현업에서 DB Query 생성이나 API 반환 형태를 맞추는 등 문자열 연산 10000 회는 충분히 가능한 일이기 때문에 성능 부하를 충분히 예상할 수 있다.

_

이번엔 StringBuilder 의 경우를 확인해 보자.

![StringBuilder 속도 테스트](https://t1.daumcdn.net/cfile/tistory/257D5236596CCAB22D)

_

보이는가! 같은 작업을 단 5밀리초 만에 수행하였다. 약 120배 이상의 성능향상을 보였다.

뿐만아니라 메모리 관리도구 등을 통해서 확인해 보면 메모리 사용량또한 현저히 차이나는 모습을 확인할 수 있다.

_

## JDK 1.5 이후

### String 자동변환

이처럼 향상된 StringBuilder의 기능을 손쉽게 적용하기 위하여 Java 컴파일러 개발자들도 많은 노력을 하였다.

JDK 1.5 이후 String 의 `+` 연산이 있을경우 자바 컴파일러에 의해서 자동으로 StringBuilder로 변환된다.

_

#### 생성된 Class 비교

그렇다면 자동변환되는 class 파일을 직접 까보기로 하자.

_

먼저 다음과 같은 java 파일을 만든다.

_

![String자동변환 테스트](https://t1.daumcdn.net/cfile/tistory/242E1F33596CC78904)

_

이클립스에서 class 파일을 열어보면 Java bytecode 가 보이는데 이는 다음과 같다.

_

![String자동변환 테스트2](https://t1.daumcdn.net/cfile/tistory/24C69933596CC78925)

_

이런 class 파일을 JD-GUI를 통해서 변환할 경우 원본 모습(String 이 `+` 연산을 하는 것) 으로 변환되기 때문에 직접 바이트코드를 해석해 보기로 했다. 20 번째줄 부터 해석하면 다음과 같이 된다.

_


```

String cString = new StringBuilder(String.valueOf(aString)).append(bString).toString();

System.out.println(cString);

```

_

이처럼 JDK 1.5 이후 부터는 StringBuilder 객체를 생성하여 append 시키도록 치환시킨다.

_

### 한계

그러나 이처럼 `+` 연산이 있는 자리에서 객체가 생성되기 때문에 이를 반복문 안에서 사용할 경우 쓸모없는 객체가 생성된다.

_

이것도 마찬가지로 class 파일을 해석해 보자.

_

![String 자동변환 반복문](https://t1.daumcdn.net/cfile/tistory/236DF73B596CC78907)

_

![String 자동변환 반복문2](https://t1.daumcdn.net/cfile/tistory/2335DE42596CC78934)

_

이처럼 18번째 줄에서 for문 안에서 StringBuilder 가 반복생성 되는 모습을 확인할 수 있다.

_

즉, 속도측면에서나, 메모리 측면에서나 StringBuilder를 직접 선언하여 만들어 주는것이 효율적이다.

_

## 결론

4줄 요약

StringBuilder 가 빠르다. 

String 을 써도 `+` 연산시 StringBuilder 로 치환되어 StringBuilder 객체 생성후 append() 연산을 한다.

반복문 안에서 생성할 경우 StringBuilder 객체를 계속 생성한다.

반복문이 아니라면 String 의 `+` 연산을 써도 무방하다. (성능 차이가 없는 것이 아니라 자바 컴파일러가 변환 시키는 것)

_

# 참고

- [[자바] String, StringBuilder, StringBuffer의 차이](http://12bme.tistory.com/42)

- [자바 성능 튜닝 이야기](https://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788966260928&orderClick=JAj)

+ Recent posts