일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- JPA
- ORM
- 링킹
- Kotlin for Java Developers
- exception
- IOC
- 자바
- 토비의스프링
- 토비의스프링3.1
- 클린코드
- 프록시
- hibernate
- lambda
- Spring
- java
- 링커
- springwebmvc
- gradle
- DispatcherServlet
- ApplicationContext
- 컴퓨터시스템
- DesignPattern
- FunctionalInterfaces
- AutoConfiguration
- 메이븐
- springboot
- beanfactory
- String
- Immutable
- 빌드툴
- Today
- Total
엔지니어로 가는 길
Java StringBuilder를 쓰는 이유 본문
Immutable
String은 immutable하다. Immutable이란 변하지 않는다는 뜻이다. 예시를 들어보자.
위와 같이 "Hello"를 담고 있는 str이라는 변수에 "Hello world"를 대입해주면 어떤 일이 벌어질까? "Hello"가 있던 공간에 " world"를 추가하는 것이 아니라 "Hello world"라는 새로운 문자열을 갖게 된다. 정확히는 str이 "Hello"가 있는 메모리 공간을 가리키던 상황에서 "Hello world"가 있는 메모리 공간을 가리키게 된다. (만약 위의 상황에서 String str2 = "Hello world"; 라는 코드를 추가한다면 이때 str2와 str1은 같은 곳을 가리키게 된다. 참고: Java String literal과 new String()의 차이(동일성과 동등성))
그럼 이건 어떨까?
출력 결과는 다음과 같다.
replace를 호출했다고 해서 str이 변하지 않는다. 왜냐하면 String은 immutable이기 때문이다. str이 가지고 있는 문자열을 교체해주고 싶다면, 정확히는 교체한 효과를 갖게하고 싶다면 replace가 리턴해주는 문자열을 받아야 한다.
다른 것도 마찬가지이다. toUpperCase(), subString(), concat() ... 모두 그런 연산을 적용한 새로운 문자열을 리턴해줄 뿐 원래의 문자열 자체를 바꾸지는 못한다.
StringBuilder와 StringBuffer
만약 매우 긴 String에 매우 많은 String 연산을 매우 많이 반복해야 하는 경우라면 어떨까? 연산마다 매번 String 객체가 만들어진다. 메모리 효율이 매우 나쁠 것이다. 이런 경우라면 StringBuilder 또는 StringBuffer를 고려해보아야 한다.
(StringBuilder와 StringBuffer는 동기적인지 비동기적인지가 다른데 StringBuilder는 비동기적이라 스레드 세이프하지 못하지만 동기적이고 스레드 세이프한 StringBuffer에 비해 효율이 좋다. 이 글의 관점에서 보면 둘은 같으니 StringBuilder 하나만 보도록 하자.)
참고: www.javatpoint.com/difference-between-stringbuffer-and-stringbuilder
StringBuilder에서 만들어지는 String은 mutable하다. 즉, 변경이 가능하다. StringBuilder는 미리 메모리 공간을 확보해두기 때문에(특정 크기의 char 배열을 만들어두기 때문에) toString 메소드를 호출하여 immutable한 String을 생성하기 전까지는 메모리 공간 안에서 char를 변경하고 추가하고 삭제할 수 있기 때문이다.
위의 사진은 stackoverflow의 한 답변이다. Single statement인 경우 컴파일러가 자동으로 StringBuilder를 이용하여 연산할 수 있지만, 반복문인 경우는 최적화하지 못하므로 사용자가 StringBuilder를 사용해주는 게 좋다는 내용이다.
참고로 StringBuilder 생성자에 capacity를 줄 수 있는데 아무것도 주지 않을 경우 default capacity는 16칸으로 32바이트(16*2byte) char 배열이 만들어진다. 만약 계속 append하여 capacity가 부족하게되는 경우 사용자가 별도로 무언가를 해주지 않아도 내부적으로 알아서 capacity를 늘린다. 아래는 테스트한 결과이다.
String 연산을 효율적으로 할 수 있다는 장점 외에도 StringBuilder는 String이 제공하지 않는 다른 연산을 제공하여 String 연산을 효과적으로 할 수 있다는 장점도 있다.
정리하자면, immutable한 String 연산을 효율적이고 효과적으로 하기 위해 StringBuilder를 사용한다.
'프로그래밍 > Java' 카테고리의 다른 글
자바를 통해 다이나믹 프록시(Dynamic Proxy)를 구현하는 방법 (8) | 2020.10.26 |
---|---|
자바 프록시와 데코레이터 패턴(Decorator Pattern)에 대해 알아보자 (0) | 2020.10.23 |
Java String으로 보는 동일성과 동등성 (0) | 2020.10.11 |
JPA @Embedded, @Embeddable, @ElementCollection 그리고 FetchType (2) | 2020.10.02 |
Java 9 Modules에 대해 알아보자 (0) | 2020.09.29 |