공부한것들을 정리하는 블로그 입니다.
String, StringBuffer, StringBuilder 차이점 본문
오랜만에 String, StringBuffer, StringBuilder 차이점에 대해 리마인드 해봅니다.
String, StringBuffer, StringBuilder 차이점
# String
- 가장 큰 차이는 String은 불변성을 가진다는 점입니다.
- 가령 "hello" 값을 가지고 있던 String 클래스의 참조변수에 "World" 문자열을 더하게 될 경우 단순히 문자열이 "helloWorld"로 수정된 것이 아니라,
- 기존에 "hello" 값이 들어가 있던 String 클래스의 참조변수가 "helloWorld"라는 값을 가지고 있는 새로운 메모리 영역을 가리키도록 변경되고, 처음 선언했던 "hello"로 값이 할당되어 있던 메모리 영역은 GC에 의해 제거 대상이 됩니다.
- 이처럼 String 클래스는 불변하기 때문에 문자열을 수정하는 시점에 새로운 String 인스턴스가 생성되기 때문에, 문자열의 추가, 수정, 삭제 등이 빈번하게 발생할 때에는 적합하지 않습니다.
- 추가로 단순 조회 연산에서는 다른 클래스에 비해 속도가 빠르며, 무결성으로 인해 멀티쓰레드 환경에서 동기화로부터 안전하다는 특징이 있습니다.
# StringBuffer, StringBuilder
- 이를 해결하기 위해 자바에서 도입한 가변성을 가지는 클래스가 바로 StringBuffer와 StringBuilder입니다.
- StringBuilder는 문자열 연산을 위해 클래스 객체를 한 개만 만들고, 길이를 변형시키며 연산을 진행할 수 있습니다.
- 여기서 StringBuffer와 StringBuilder의 차이는 동기화의 지원 유무입니다. StringBuffer는 동기화 키워드를 지원하기 때문에 멀티쓰레드 환경에서 안전하고 StringBuilder는 동기화를 지원하지 않지만 단일쓰레드 환경에서 성능이 더 뛰어나다는 장점이 있습니다.
# 더 생각해볼 만한 내용
$ String 객체가 관리되는 메모리 영역에 대해 생각해보기
$ String vs StringBuilder의 속도(성능) 차이에 대해 생각해보기
$ String 객체의 메모리 사용 원리?
$ JDK 1.5 버전에서 String을 써도 상관없다?
# String 객체가 관리되는 메모리 영역에 대해 생각해보기
- String은 클래스이며, 기본타입이 아닌 참조타입이다.
- 따라서 String 객체는 'Heap 영역'의 String constant pool이라는 곳에서 따로 관리된다.
* 기본타입은 'stack 영역'에 값이 저장된다.
* 메모리(RAM)에서 실행되는 '프로세스'는 code-data-heap-stack 영역으로 나뉜다
* code에는 소스코드가, data에는 전역변수 및 static 변수가, heap은 런타임에 동적 할당되는 데이터가, stack은 컴파일 타임에 함수호 출시 지역변수 및 매개변수가 저장된다.
* '멀티프로세스'는 각각 프로세스별로 각각 고유한 [code-data-heap-satck] 영역을 가진다. 프로세스 간에 데이터 전달이 필요할 경우 'IPC'를 통해 해결한다.
* 'IPC'는 원칙적으로 독립적인 주소 공간을 갖는 프로세스 간에 주소 공간을 참조를 위한 방식으로 대표적으로 '공유메모리 방식'과 '메시지전달 방식'이 있다.
* '공유메모리 방식'은 메모리상에 shared memory를 확보하여 read/write를 통해 통신하여 속도가 빠른 장점이 있으나 동기화 문제가 야기될 수 있다.
* '메시지전달 방식'은 커널을 통해 send/receive 연산으로 데이터를 전달하는 방식으로 속도는 느리지만 동기화 문제로부터 안전하다
# String vs StringBuilder의 속도(성능) 차이에 대해 생각해보기
- 속도 측정 및 비교 (옛날 글 주의) : https://drsggg.tistory.com/83
- 속도 차이의 원인은 결국 가비지 컬렉터 때문입니다.
1. String 클래스의 객체가 재할당 될 때마다 새로운 객체를 생성하게 되고
2. 문자열 연산이 많아질수록 오버헤드가 발생하게 되며
3. 이때 GC가 수행되면서 성능 저하(속도)
* JVM, GC, 자바의 구동원리 : https://drsggg.tistory.com/562
# String 객체의 메모리 사용 원리?
1. String 클래스의 객체는 재할당 될 때마다 메모리 점유량이 늘어난다
ex) String은 address=100 -> 150 -> 200 순으로 길이가 변경될 경우 '주소'도 재할당 되면서 변경됨
ex) StringBuilder는 address=100 에서 길이가 변경되어도 '주소'는 재할당 되지 않고 진행
2. 메모리 부족시 GC작업에 의해 추가적인 자원이 소모된다
- 오버헤드가 발생한다고 표현한다.
ex) 문자열 연산이 많아질수록 -> 계속적으로 문자열을 만드는 오버헤드가 발생
- 결국 성능 저하는 가비지컬렉터 때문이다.
- 자바의 성능을 향상시키기 위해서는 GC를 얼마나 적게 돌릴 것인지를 고려해야 한다
# JDK 1.5 버전에서 String을 써도 상관없다?
- JDK 1.5 버전 이후로는 컴파일 단계에서 String 객체를 사용하여도 내부적으로는 StringBuilder로 컴파일되도록 변경되었습니다.
- 따라서 String 클래스를 활용하여도 StringBuilder와 성능상으로 차이가 없습니다.
- 단, 반복 루프를 사용하여 문자열을 더할 경우에는 객체를 계속 추가한다는 사실에는 변함이 없기 때문에 오버헤드가 발생할 수 있습니다.
- 따라서 String 클래스를 사용하는 대신, thread-safe 해야 한다면 StringBuffer를 thread-safe를 고려하지 않아도 된다면 StringBuilder를 사용할 수 있습니다.
'JAVA > 공부' 카테고리의 다른 글
자바의신 부록, 요약본 (0) | 2022.08.01 |
---|---|
자바의신 20장 java.lang (0) | 2022.07.12 |
자바의신 19장 JVM (0) | 2022.07.12 |
링크) 왜 Enum을 사용할까? (0) | 2022.05.26 |
추상클래스와 인터페이스 (0) | 2022.05.18 |
JVM, GC, 자바의구동원리 (0) | 2022.05.17 |
JVM에 대하여 정리 (0) | 2022.04.30 |
좋은 객체 지향 설계의 5가지 원칙(SOLID) (0) | 2022.04.24 |