>  기사  >  Java  >  Java StringBuilder 및 StringBuffer 소스 코드 분석

Java StringBuilder 및 StringBuffer 소스 코드 분석

高洛峰
高洛峰원래의
2017-01-22 11:28:401120검색

StringBuilder와 StringBuffer는 문자열 연산에 일반적으로 사용되는 두 가지 클래스입니다. 우리 모두 알고 있듯이 StringBuilder는 스레드로부터 안전하지 않지만 StringBuffer는 스레드로부터 안전합니다. 전자는 JDK1.5에 추가되었고 후자는 JDK1.0에서 사용 가능했습니다. 내부 구현을 분석해 보겠습니다.

1. 상속 관계

public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
 
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence

보시다시피 두 클래스의 상속 관계는 완전히 동일합니다. 직렬화 가능은 직렬화할 수 있는 플래그입니다. CharSequence 인터페이스에는 charAt(), length(), subSequence() 및 toString() 메서드가 포함되어 있습니다. String 클래스도 이 인터페이스를 구현합니다. 여기서 초점은 StringBuilder 및 StringBuffer의 대부분 작업 구현을 캡슐화하는 추상 클래스 AbstractStringBuilder입니다.

2. AbstractStringBuilder

1. 변수 및 구성 방법

char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
  value = new char[capacity];
}

AbstractStringBuilder는 구성 가능한 문자열을 저장하기 위해 내부적으로 char[] 배열을 사용합니다. 초기 용량 방식을 지정할 때.

2. 용량 확장

rree

확장 방법은 궁극적으로 ExpandCapacity()에 의해 구현됩니다. 이 방법에서는 먼저 용량을 원래 용량에 2를 더한 값으로 확장합니다. 이때 여전히 지정된 용량보다 작은 경우 새 용량을 최소 용량으로 설정합니다. 그런 다음 오버플로되는지 확인합니다. 그렇다면 용량을 Integer.MAX_VALUE로 설정합니다. 마지막으로 값이 복사되는데 이는 확실히 시간이 많이 걸리는 작업입니다.

3.append() 메소드

public void ensureCapacity(int minimumCapacity) {
  if (minimumCapacity > 0)
    ensureCapacityInternal(minimumCapacity);
}
 private void ensureCapacityInternal(int minimumCapacity) {
  // overflow-conscious code
  if (minimumCapacity - value.length > 0)
    expandCapacity(minimumCapacity);
}
void expandCapacity(int minimumCapacity) {
  int newCapacity = value.length * 2 + 2;
  if (newCapacity - minimumCapacity < 0)
    newCapacity = minimumCapacity;
  if (newCapacity < 0) {
    if (minimumCapacity < 0) // overflow
      throw new OutOfMemoryError();
    newCapacity = Integer.MAX_VALUE;
  }
  value = Arrays.copyOf(value, newCapacity);
}

append()는 가장 일반적으로 사용되는 메소드이며 다양한 형태의 오버로딩이 있습니다. 위의 내용은 문자열을 추가하는 데 사용되는 것 중 하나입니다. str이 null인 경우,appendNull() 메서드가 호출됩니다. 이 방법은 실제로 'n', 'u', 'l' 및 'l' 문자를 추가합니다. null이 아니면 먼저 용량을 확장한 후 String의 getChars() 메서드를 호출하여 값 끝에 str을 추가합니다. 마지막으로 객체 자체가 반환되므로,append()를 계속해서 호출할 수 있습니다.

3. StringBuilder

AbstractStringBuilder는 이미 대부분의 필수 메서드를 구현했으며 StringBuffer만 호출하면 됩니다. StringBuilder의 구현을 살펴보겠습니다.

1. 생성자

public AbstractStringBuilder append(String str) {
    if (str == null)
      return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
  }

StringBuilder의 기본 용량은 16임을 알 수 있습니다. 물론 초기 용량을 지정하거나 기존 문자 시퀀스를 사용하여 StringBuilder 개체에 초기 값을 할당할 수도 있습니다.

2.append() 메소드

public StringBuilder() {
  super(16);
}
public StringBuilder(int capacity) {
  super(capacity);
}
public StringBuilder(String str) {
  super(str.length() + 16);
  append(str);
}
public StringBuilder(CharSequence seq) {
  this(seq.length() + 16);
  append(seq);
}

append()에는 오버로드된 메소드가 많이 있으며 그 중 두 가지가 여기에 나열되어 있습니다. 분명히 여기에는 직접 호출되는 상위 클래스 AbstractStringBuilder의 메서드가 있습니다.

3. toString()

public StringBuilder append(String str) {
  super.append(str);
  return this;
}
public StringBuilder append(CharSequence s) {
  super.append(s);
  return this;
}

toString() 메서드는 원본 객체와 메모리를 공유하지 않는 새로운 String 객체를 반환합니다. 실제로 AbstractStringBuilder의 subString() 메서드도 마찬가지입니다.

4. SringBuffer

StiringBuffer는 동기화를 달성하기 위해 다음과 같은 많은 메소드가 lSynchronized 수정을 사용한다는 점을 제외하면 StringBuilder와 유사합니다.

public String toString() {
  // Create a copy, don&#39;t share the array
  return new String(value, 0, count);
}


보시다시피 실제로 메소드 앞에는 동기화가 추가되어 있습니다.
또한 위의 추가() 및 setLength() 메서드에는 toStringCache 변수가 있습니다. 이 변수는 가장 최근의 toString() 메소드의 캐시에 사용됩니다. StringBuffer가 수정될 때마다 이 변수에는 null 값이 할당됩니다. StringBuffer의 toString은 다음과 같습니다.

public synchronized int length() {
    return count;
}
public synchronized StringBuffer append(String str) {
  toStringCache = null;
  super.append(str);
  return this;
}
public synchronized void setLength(int newLength) {
  toStringCache = null;
  super.setLength(newLength);
}

이 방법에서는 toStringCache가 null인 경우 먼저 캐시됩니다. 최종 반환된 String 객체는 약간 다릅니다. 이 생성자에는 true 매개변수도 있습니다. String의 소스 코드를 찾아 살펴보세요.

public synchronized String toString() {
  if (toStringCache == null) {
    toStringCache = Arrays.copyOfRange(value, 0, count);
  }
  return new String(toStringCache, true);
}

이 구성 방법으로 생성된 String 객체는 실제로 문자열을 복사하지 않고 값을 가리키는 것으로 나타났습니다. 구성 매개변수입니다. 이는 요소 복사 시간을 절약하기 위한 것입니다. 그러나 이 생성자에는 패키지 액세스 권한이 있으므로 일반적인 상황에서는 호출할 수 없습니다.

요약

StringBuilder와 StringBuffer는 모두 변경 가능한 문자열입니다. 전자는 스레드에 안전하지 않으며 후자는 스레드로부터 안전합니다.

대부분의 StringBuilder 및 StringBuffer 메소드는 상위 클래스 AbstractStringBuilder의 구현을 호출합니다. 확장 메커니즘은 먼저 용량을 원래 용량의 2배에 2를 더한 값으로 변경합니다. 최대 용량은 Integer.MAX_VALUE(0x7fffffff)입니다.

StringBuilder와 StringBuffer의 기본 용량은 16입니다. 확장으로 인한 시간 소모를 피하기 위해서는 문자열의 크기를 미리 예측해 두는 것이 가장 좋습니다.

위 내용은 이 기사의 전체 내용입니다. Java에서 문자열을 연산하는 데 일반적으로 사용되는 두 가지 클래스인 StringBuilder 및 StringBuffer를 배우는 것이 도움이 되기를 바랍니다.

Java StringBuilder 및 StringBuffer 소스 코드 분석과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.