# String, StringBuilder, StringBuffer 차이 - String은 immutable하기 때문에 '+' 연산 시, 새로운 String 객체를 만들어낸다. -> **메모리를 많이 사용하게 된다는 단점이 있다.** - 사실 JDK1.5부터 내부적으로는 연산 시 StringBuilder를 사용한다. 그런데 반복문 안에서 연산을 계속한다면 StringBuilder 객체가 연산 횟수만큼 생성되기 때문에 상대적으로 느릴 수 있다. 따라서 문자열 연산이 많은 경우 StringBuilder 사용 고려 - 그러나 StringBuilder/StringBuffer는 mutable 하다는 차이점이 있음. ## StringBuilder와 StringBuffer의 차이점은? ``` 여러 스레드에서 동시에 작업할 때 안전한지 여부 - 안전하다면? ThreadSafe 하다. - 안전하지 않다면? ThreadSafe 하지 않다고 한다. ``` StringBuffer - Synchronized(동기화 보장) -> TreadSafe StingBuilder - Asynchronized -> ThreadSafe 하지 않기 때문에 Threadsafe 한 상황이 필요하지 않다면 StringBuilder를 사용하는 것이 오버헤드를 막는다. -> **왜 ThreadSafe하면 오버헤드가 발생할까?** ### 메소드 안에서 선언하여 사용할 때는 어떤 것을 사용하는 것이 좋을까? - 서로 다른 Thread와의 경합이 발생하지 않기 때문에 StringBuilder를 사용하는 게 낫다. StringBuffer를 사용하는 건 리소스 낭비다. - 클래스 레벨이 아니라 메소드 레벨로 한정지으면 공유 변수가 있을수가 없으니 race condition 자체가 발생할 수 없음. ### 왜 ThreadSafe하면 오버헤드가 발생할까? - StringBuffer 내부에 synchronized 키워드를 사용하기 때문에 하나의 스레드가 접근하면 다른 스레드가 접근하지 못하도록 락을 건다. ### Synchoronized - Lock 걸어주는 것 - 왜? 하나 이상의 Thread가 동시에 접근했을 때, 그 연산에 대한 값의 무결성을 보장하기 우함 ### String Constant Pool - 스트링 객체 생성 방법은 2가지가 있다. - 리터럴 방식, "" -> heap 영역 내 Constant Pool 공간에 저장 - new String() -> heap 영역 내 저장 - 리터럴 방식으로 만들었을 때 장점은? - 동일한 값이라면, 새로운 객체를 만드는 게 아니라 Constant Pool에 있는 값을 참조해서 사용할 수 있다. 즉, 메모리 주소 공유(캐싱, 자바에서 String이 불변한 이유 중 하나이다.) - 이에반해, new String() 방식으로 만들었을 때는 값이 동일하더라도 heap 영역에 하나 더 만든다. -> 메모리를 효율적으로 사용하기 위해선 리터럴 방식으로 만든다. ### StringJoiner - 여러 문자들을 연결할 때 delimiter, prefix, sufix 를 간단하게 추가할 수 있는 클래스 ```java StringJoiner sj = new StringJoiner("-", "[", "]"); sj.add("a"); sj.add("b"); sj.add("c"); sj.add("d"); System.out.println(sj); // [a-b-c-d] ``` https://docs.oracle.com/javase/8/docs/api/java/util/StringJoiner.html --- ## 내 생각 - 자바 동기화 방식(synchronized, atomic, volitile)에 대해서 좀 더 자세히 공부해봐야겠다. - 자바에서 String을 불변하게 만든 이유 3가지(캐싱, 동기화, 보안)에 대해서도 좀 더 공부해봐야겠다. - String/StringBuilder/StringBuffer 성능 차이가 수치상으로 얼마나 차이가 나는지도 좀 더 공부해봐야겠다. - StringJoiner는 유용해보이는데 구체적으로 언제 유용하게 쓸 수 있을진 잘 모르겠다. - ~~StringBuilder, StringBuffer를 메소드 안에서 선언하여 사용할 때 Thread 간 경합이 발생하지 않는다는 게 정확하게 이해가 잘 안된다. 이상민님 책에 있던 내용인데 이번 주안으로 이해를 못하면 메일로 문의를 해보면 좋겠다.~~ -> 메소드 안에서는 공유 변수가 없기 때문에 race condition 자체가 발생할 수가 없기 때문!