[JAVA] String과 == 연산, String '+' 연산과 StringBuilder, StringBuffer의 차이점

String과 == 연산

자바에서는 '=='을 사용할 경우 인스턴스의 참조 값을 비교합니다.
그래서 객체를 비교할 경우는 아래처럼 Object.equals() 메서드를 오버라이딩해서 사용합니다.

class Int {
    int a = 100;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Int anInt = (Int) o;
        return a == anInt.a;
    }

    @Override
    public int hashCode() {
        return Objects.hash(a);
    }
}

String은 자바에서 문자열을 다루는 객체입니다.
그렇다면 String를 비교할 때 == 연산을 사용하면 결과가 어떻게 나올까요?

String a = "Hello World";
String b = "Hello World";

System.out.println(a == b);

자바에서 '=='는 레퍼런스 비교이기 때문에 false가 출력될까요?

결과는 true가 나옵니다.

자바에서는 String literal로 생성하면 String 값을 heap 영역 내의 Constant Pool에 저장해 재사용합니다.

a와 b는 "Hello World"라는 같은 문자열을 가지기 때문에,
하나의 메모리 공간을 같이 공유하게 됩니다.

그래서 당연히 a와 b는 동일한 레퍼런스를 가지기 때문에 '==' 비교에서 true가 나오게 되는 것입니다.

String '+' 연산

위에서 자바 String은 Constant Pool을 사용한다는 것을 알았습니다.
그럼 문자열에 '+' 연산을 사용할 경우는 기존의 가리키던 메모리에 문자열이 추가로 더해지는 것일까요?

아닙니다!
자바 String에 '+' 연산을 사용할 경우 다음과 같이 새로운 메모리 공간에 문자열을 저장하고 다시 해당 메모리 공간을 가리키는 구조로 문자열이 생성됩니다.

따라서 여러번의 문자열 연산이 필요할 때 String과 '+' 연산을 사용하기 보다 크기가 유연하게 변하는 StringBuilder, StringBuffer를 사용해야 합니다.

StringBuilder, StringBuffer의 차이점

문자열 연산에서 String 객체와 '+' 연산을 사용하는 것보다 StringBuilder, StringBuffer을 사용하는 게 메모리 효율성에 더 좋다는 것을 알았습니다.
그럼 StringBuilder, StringBuffer의 차이점은 무엇일까요?

동기화(Synchronization)에서 차이가 납니다.

StringBuffer는 동기화를 지원하지만 StringBuilder는 동기화를 지원하지 않습니다.

@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str) {
	toStringCache = null;
	super.append(str);
	return this;
}

synchronized 키워드는 여러 개의 스레드가 하나의 자원에 접근하려 할 때 현재 데이터를 사용하고 있는 스레드를 제외하고 나머지 스레드들이 데이터에 접근할 수 없도록 막는 역할을 합니다.
예를 들어 A 스레드가 append() 동기화 블록에 접근 및 실행하는 동안 B 스레드는 append() 동기화 블록에 들어가지 못하고 block 상태가 됩니다.
이후 A 스레드가 append() 동기화 블록에서 빠져나온다면, 그때 B 스레드는
running 상태가 되며 append() 동기화 블록에 접근할 수 있습니다.

반면에 StringBuilder는 동기화를 지원하지 않기 때문에 단일 스레드 환경에서 StringBuffer에 비해 성능이 뛰어납니다.

결론

  • 불변성을 갖는 문자열이 필요하다면 String을 사용
  • 단일 스레드 환경에서 문자열 연산이 빈번히 발생하는 경우 StringBuilder 사용
  • 멀티 스레드 환경에서 문자열 연산이 빈번히 발생하는 경우 StringBuffer 사용

참고

[Java] String, StringBuffer, StringBuilder 차이 및 장단점
StringBuilder와 StringBuffer는 무슨 차이가 있는가?

좋은 웹페이지 즐겨찾기