거누의 개발노트

Java - String, StringBuilder, StringBuffer의 차이 본문

Java

Java - String, StringBuilder, StringBuffer의 차이

Gogozzi 2022. 3. 3. 07:01
반응형
String

String은 불변 객체이다. 

String str = "hello";
str = str + " Java";

 

1. 처음에 hello 라는 문자열을 변수에 초기화 했다.

str 변수에 담긴 hello 문자열

2. hello Java를 새로 초기화 했고, 원래 있던 hello 라는 문자열은 가비지 컬렉터(garbage collection)에 의해 사라지게 된다.

결국 String은 기존에 있던 문자열에 추가하는 형태가 아니라 새로운 인스턴스를 생성해서 문자열이 수정된 것 처럼 보이는것이다.

 

StringBuffer / StringBuilder

StringBuffer / StringBuilder은 가변 객체이다. 

StringBuffer sb = new StringBuffer("hello");
sb.append(" Java");

1. StringBuffer를 선언하고 hello를 추가했다.

2. hello가 담겨있는 StringBuffer에 Java를 추가했다.

문자열의 추가,수정,삭제가 빈번하게 발생할 경우라면 String 클래스가 아닌 StringBuffer/StringBuilder를 사용해야 더 좋은 성능이 보장된다.

StringBuffer / StringBuilder 에서 사용가능한 메소드 정리

StringBuffer sb = new StringBuffer("hello");
sb.append(" Java");

System.out.println("처음 상태 : " + sb); //처음상태 : hello Java
System.out.println("문자열 String 변환 : " + sb.toString()); //String 변환하기
System.out.println("문자열 추출 : " + sb.substring(2,4)); //문자열 추출하기
System.out.println("문자열 추가 : " + sb.insert(0,"gogo ")); //문자열 추가하기
System.out.println("문자열 삭제 : " + sb.delete(2,4)); //문자열 삭제하기
System.out.println("문자열 연결 : " + sb.append("!!!")); //문자열 붙이기
System.out.println("문자열의 길이 : " + sb.length()); //문자열의 길이구하기
System.out.println("용량의 크기 : " + sb.capacity()); //용량의 크기 구하기
System.out.println("문자열 역순 변경 : " + sb.reverse()); //문자열 뒤집기

 

StringBuffer vs StringBuilder
가장 큰 차이점은 동기화의 유무로 StringBuffer는 동기화 키워드를 지원하여 멀티쓰레드 환경에서 안전하다.
* String도 불변성을 가지기 때문에 멀티쓰레드 환경에서 안전성을 가지고 있다.
반대로 StringBuilder는 동기화를 지원하지 않기때문에 멀티쓰레드 환경에서 사용하는 것은 적합하지 않지만 동기화를 고려하지 않는 만큼 단일쓰레드에서의 성능은 StringBuffer 보다 뛰어납니다.

 

어떤 환경에 적용해야하는지
String               :  문자열 연산이 적고 멀티쓰레드 환경일 경우 - Thread Safe ( o )
StringBuffer    :  문자열 연산이 많고 멀티쓰레드 환경일 경우 - Thread Safe ( o )
StringBuilder   :  문자열 연산이 많고 단일쓰레드이거나 동기화를 고려하지 않아도 되는 경우   - Thread Safe ( x )

 

Thread Safe

Multi Thread 프로그래밍에서 여러 Thread로부터 어떤 method나, variable, object에 동시에 접근이 이뤄져도 프로그램의 실행에 문제가 없다는것을 의미한다.

하나의 function이 한 Thread로 부터 호출되어 실행 중일 때, 다른 Thread가 동일한 함수를 호출하여 동시에 실행되더라도 각 Thread에서 함수의 수행 결과가 바르게 나오는 것이다.

 

String 이 불변 객체인 이유?

String이 불변이기 때문에 String Pool도 존재할 수 있다.

1.  String Pool

어떤 프로그래밍 언어라도 String 타입은 매우 빈번하게 사용된다. 그래서 Java에서는 String Pool이라는 공간에 String을 포함시켜서, 매번 String 객체를 새로 생성하기보다는 값이 같은 String이라면 String Pool에 있는 객체를 재사용할 수 있도록 구현했다. 

만약 String이 가변 객체라면 String Pool 이라는 공간을 공유 할 필요가 없어진다.

 

2.  보안

Java에서 메서드의 파라미터로 String을 받는 경우는 매우 흔하다.
예를 들어 사용자의 이름이나 패스워드, 혹은 네트워크 연결을 위한 포트 번호나 connection URL, 파일 이름 등 중요한 정보를 String으로 받을 때가 많다.

JVM의 class loader가 class loading을 수행할 때도 마찬가지다.
만약 String 이 가변이라면 중간에 String 이 변하게되 보안에 취약해진다.

 

3.  동기화

객체가 불변이면 멀티 스레드 환경에서도 값이 바뀔 위험이 없기 때문에, 자연스럽게 thread-safe한 특성을 갖게 되고, 동기화와 관련된 위험 요소에서 벗어날 수 있다. 여러 스레드에서 동시에 접근해도 별다른 문제가 없다.

또한, String의 경우 한 스레드에서 값을 바꾸면, 해당 객체의 값을 수정하는 것이 아니라 새로운 객체를 String Pool에 생성한다. 따라서 thread-safe하다고 볼 수 있다

 

4.  Hashcode Caching

String의 hashCode() 메서드 구현을 보면, 아직 hash 값을 계산한 적이 없을 때 최초 1번만 실제 계산 로직을 수행한다.
이후부터는 이전에 계산했던 값을 그냥 리턴만 하도록 되어 있다. 즉 hashCode 값을 캐싱(caching)하고 있다.

 

 

::결론 적으로 이러한 성능상의 이유로 불변객체로 구현한것이다.

:: 용도를 정확히 모르고 String만 주구장창 사용했던 것 같다. 지금이라도 용도에 맞게 잘 사용해봐야겠다.

출처: https://starkying.tistory.com/entry/why-java-string-is-immutable 
출처 : https://ifuwanna.tistory.com/221

반응형
Comments