@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)
'java' 카테고리의 다른 글
[Spring] Spring Boot & Rest API (1) (0) | 2020.05.14 |
---|---|
[Spring] Spring Boot & 테스트 코드 작성 (3) - MockMvc (0) | 2020.05.13 |
[Spring] Spring Boot & 테스트 코드 작성 (2) - Mock, Mockito (1) | 2020.05.11 |
[Spring] Spring Boot & 테스트 코드 작성 (1) - JUnit (0) | 2020.05.08 |
[Spring] VSCode & Spring Boot (0) | 2020.05.08 |