문자를 이어 붙이기 위해 StringBuilderStringBufferappend() 메소드를 사용하는데 내부적으로 char[] 배열을 사용

append() 메소드가 호출되면, 추가할 문자열의 길이와 현재 배열의 남은 공간을 확인하고 있으면 그대로 삽입

현재 배열의 크기가 부족할 때

public final class MyStringBuilder {
    private char[] value;
    private int count;
//MyStringBuilder는 초기 크기 16의 char[] 배열을 가짐
    public MyStringBuilder() {
        value = new char[16]; // 초기 크기 설정
        count = 0;
    }
// 문자열을 추가할 때마다 append() 메소드가 호출됨
    public MyStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacity(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
// 현재 배열의 크기가 충분한지 확인하고 만약 부족하면 expandCapacity() 메소드를 호출
    private void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity - value.length > 0) {
            expandCapacity(minimumCapacity);
        }
    }
// **expandCapacity()**: 배열의 크기를 2배로 늘리거나, 필요한 최소 크기로 설정하여 새 배열을 생성. 기존 배열의 내용을 새 배열로 복사
    private void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2;
        if (newCapacity - minimumCapacity < 0) {
            newCapacity = minimumCapacity;
        }
        char[] newValue = new char[newCapacity];
        System.arraycopy(value, 0, newValue, 0, count);
        value = newValue;
    }
// 내부 char[] 배열을 문자열로 변환하여 반환
    @Override
    public String toString() {
        return new String(value, 0, count);
    }

    public static void main(String[] args) {
        MyStringBuilder sb = new MyStringBuilder();
        sb.append("Hello");
        sb.append(" ");
        sb.append("World!");
        System.out.println(sb.toString()); 
        // 출력: Hello World!
    }
}

String과 달리 StringBuilder 객체를 새로 만드는 것이 아니기 때문에 주소는 그대로 유지됨