Java의 정석_기초편

StringBuffer클래스

DJDU 2022. 10. 27. 16:27

StringBuffer클래스

  • String처럼 문자형 배열(char[])을 내부적으로 가지고 있다.
  • 그러나, String클래스와 달리 내용을 변경할 수 있다(mutable).
더보기

String처럼 문자형 배열(char[])을 내부적으로 가지고 있다.

StringBuffer클래스도 문자열을 저장&다루기 위한 클래스이다.

public final class StringBuffer implements java.io.Serializable {
    private char[] value;
        ...
}

 

그러나, String클래스와 달리 내용을 변경할 수 있다(mutable)

String클래스는 내용 변경이 불가한 불변클래스이다. 하지만, StringBuffer는 '내용' 변경 가능한 가변 클래스이다.

문자열 "abc"를 저장하기 위한 StringBuffer인스턴스를 만든다면, 그림이 이렇게 된다.

char[] 배열이 만들어지고, 그 안에 문자 'a', 'b', 'c'가 저장된다.
sb.append("123"); // sb의 내용 뒤에 "123"을 추가한다.

여기에 append("123")를 사용하면, 새로운 문자열"123"을 뒤에 추가한다.

즉, StringBuffer클래스는 내용이 변경 가능한 가변 클래스이다. 이처럼 문자열을 저장할 때는 String클래스를 사용하지만, 문자열 조작을 많이 해야 할 경우에는 StringBuffer클래스를 사용해야 한다.

 

StringBuffer의 생성자

  • 배열은 길이 변경 불가. 공간이 부족하면 새로운 배열 생성해야 함 ⭐️
  • StringBuffer는 저장할 문자열의 길이를 고려해서 적절한 크기로 생성해야 함
더보기

배열은 길이 변경 불가. 공간이 부족하면 새로운 배열 생성해야 함. ⭐️

1. 더 큰 배열 생성

상황 : 길이가 5인 배열을 만들어서 1~5를 저장했는데, 6을 추가로 저장하고 싶다. 

하지만, '공간 부족'하다. 공간을 늘려주면 좋겠지만 배열은 '길이 변경불가'하기 때문에 새로운 배열을 만들어야 한다. 보통 x2, 길이가 두 배인 배열을 생성한다.

2. 기존 내용 복사

배열을 만든 후 기존의 배열 내용을 복사한다. 

3. 참조 변경

마지막으로 '참조 변경'을 해야 한다. 위 배열은 더 이상 사용하지 않기 때문에, 참조를 끊고 참조변수 arr이 새로운 배열을 가리키게 해야 한다. 그럴려면, 새로운 배열의 주소를 참조변수 arr에 저장하면 된다. 그 결과 참조변수 arr은 새로 생성된 배열의 주소값인 0x200이 저장되고, 새로 생성된 배열을 가리키게 된다. 이렇게 3단계 처리를 해야 한다.

정리

① 더 큰 배열 생성

② 기존 내용 복사

③ 참조 변경

 

| 참고 | 코드는 책을 보고 적더라도, 일단 말로 세 가지 단계를 거쳐야 된다는 정도는 할 수 있어야 한다.

 

StringBuffer는 저장할 문자열의 길이를 고려해서 적절한 크기로 생성해야 함

이런 일들이 자주 일어나면 성능이 떨어질 수밖에 없다. 따라서 처음 만들 때, 문자열의 길이를 고려해서 적절한 크기를 갖는 StringBuffer를 만들어야 한다. 그래서 생성자 중에 StringBuffer(int length)가 있다. 가능하면 적절한 크기를 지정해줘서 공간이 부족한 일이 없도록 해야 한다. 그래서 '적절한 크기'를 지정해주는 것이 매우 중요하다.  

 

StringBuffer의 변경

  • StringBuffer는 String과 달리 내용 변경이 가능하다.
  • append()는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환
더보기

StringBuffer는 String과 달리 내용 변경이 가능하다.

StringBuffer sb = new StringBuffer("abc");
sb.append("123"); // sb의 내용 뒤에 "123"을 추가한다.
StringBuffer sb = new StringBuffer("abc");
sb.append("123");

 

append()는 지정된 내용을 StringBuffer에 추가 후, StringBuffer의 참조를 반환

StringBuffer의 주요 메서드

  1. append() : 끝에 문자열 추가
  2. delete() : 끝에 문자열 삭제
  3. insert() : 끝에 문자열 삽입

이러한 StringBuffer메서드들의 특징은 반환타입이 자기 자신(StringBuffer)이라는 것이다.

StringBuffer sb2 = sb.append("ZZ"); // sb의 내용 뒤에 "ZZ"를 추가한다.
System.out.println(sb);             // abc123ZZ
System.out.println(sb2);            // abc123ZZ
오른쪽 처럼 보다 간경한 코드로 작성할 수 있다.

이렇게 할 수 있는 이유는 append메서드의 반환타입이 자기 자신(StringBuffer)이기 때문이다.

 

StringBuffer의 비교

  • StringBuffer는 equals()가 오버라이딩되어있지 않다.(주소 비교)
  • StringBuffer를 String으로 변환 후에 equals()로 비교해야 한다.
더보기

StringBuffer는 equals()가 오버라이딩되어있지 않다.(주소 비교)

String은 equals()가 오버라이딩되어있지만, StringBuffer는 equals()가 오버라이딩되어있지 않다. 그렇다는 얘기는 '주소 비교'를 한다는 의미이다. 반면 String은 equals()가 오버라이딩되어있기 때문에 '내용 비교'를 한다. 

'주소 비교'는 코드가 this==obj 이렇게 되어 있다는 의미이다.

서로 다른 객체를 비교할 때 내용이 같더라도 '주소 비교'를 하기 때문에 false를 출력한다.

StringBuffer를 String으로 변환 후에 equals()로 비교해야 한다.

따라서, StringBuffer인스턴스를 비교하기 위해서는 String으로 변환한 후에 equals()로 비교해야 한다.

String s  = sb.toString();        // StringBuffer를 String으로 변환
String s2 = sb2.toString();

System.out.println(s.equals(s2)); // true

 

StringBuffer클래스의 생성자와 메서드

 

예제9-12

더보기

메서드 체이닝

  • 메서드를 연속으로 사용하는 것
public class Ex9_12 {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("01");
        StringBuffer sb2 = sb.append(23);

        sb.append('4').append(56);  // 메서드 체이닝