개요
StringBuilder와 StringBuffer는 쉽게 혼란스러운 두 가지 개념입니다. 이 기사는 소스 코드에서 시작하여 단순히 두 가지의 유사점과 차이점을 살펴 봅니다.
이 두 가지 중 하나는 스레드-안전이며 스레드-안전한 하나는 비효율적이라는 것을 쉽게 알 수 있습니다.
Java Doc의 설명
Java Doc은 소스 코드를 작성하는 사람들이 작성한 주석입니다. Java Doc을 먼저 살펴 보겠습니다.
StringBuilder
변한 캐릭터 순서. 이 클래스는 StringBuffer와 호환되는 API를 제공하지만 동기화를 보장하지 않습니다. 이 클래스는 문자열 버퍼가 단일 스레드에 의해 사용되는 장소에서 StringBuffer의 드롭 인 교체로 사용하도록 설계되었습니다 (일반적으로 경우와 같이). 가능한 경우,이 클래스는 대부분의 구현에서 더 빨리 StringBuffer를 선호하는 것이 좋습니다.
StringBuilder의 주요 작업은 Append and Insert 메소드이며, 모든 유형의 데이터를 수락하도록 과부하됩니다. 각각은 주어진 데이텀을 문자열로 효과적으로 변환 한 다음 해당 문자열의 문자를 문자열 빌더에 추가하거나 삽입합니다. Append 메소드는 항상 빌더 끝에 이러한 문자를 추가합니다. 삽입 메소드는 지정된 지점에서 문자를 추가합니다.
예를 들어, z가 현재 내용이 "시작"인 문자열 빌더 객체를 참조하면, 메소드를 호출하면 z.append ( "le")가 문자열 빌더에 "starkle"을 포함하는 반면, z.insert (4, "le")는 문자열 빌더가 "Starlet"을 포함하도록 변경합니다.
일반적으로 SB가 StringBuilder의 인스턴스를 참조하면 sb.append (x)가 sb.insert (sb.length (), x)와 동일한 효과를 갖습니다.
모든 스트링 빌더는 용량이 있습니다. 문자열 빌더에 포함 된 문자 시퀀스의 길이가 용량을 초과하지 않는 한, 새로운 내부 버퍼를 할당 할 필요는 없습니다. 내부 버퍼가 오버플로되면 자동으로 더 커집니다.
StringBuilder 인스턴스는 여러 스레드에서 사용하기에 안전하지 않습니다. 이러한 동기화가 필요한 경우 java.lang.stringbuffer를 사용하는 것이 좋습니다.
달리 명시되지 않는 한,이 클래스의 생성자 또는 방법에 널 인수를 전달하면 NullPointerException이 발생하게됩니다.
부터:
1.5
작가:
마이클 맥 클로 스키
또한 참조 :
java.lang.stringbuffer
java.lang.string
StringBuffer
스레드-안전, 변이 가능한 캐릭터 시퀀스. 문자열 버퍼는 문자열과 같지만 수정할 수 있습니다. 언제든지 특정 문자 순서가 포함되어 있지만 시퀀스의 길이와 내용은 특정 메소드 호출을 통해 변경 될 수 있습니다.
문자열 버퍼는 여러 스레드에서 사용하기에 안전합니다. 방법은 필요한 경우에 동기화되므로 특정 인스턴스의 모든 작업이 관련된 각 개별 스레드가 작성한 메소드 호출 순서와 일치하는 일부 직렬 순서로 발생하는 것처럼 동기화됩니다.
StringBuffer의 주요 작업은 Append and Insert 메소드이며, 모든 유형의 데이터를 수락하도록 과부하됩니다. 각각은 주어진 데이텀을 스트링으로 효과적으로 변환 한 다음 해당 문자열의 문자를 문자열 버퍼에 추가하거나 삽입합니다. Append 메소드는 항상 버퍼 끝에 이러한 문자를 추가합니다. 삽입 메소드는 지정된 지점에서 문자를 추가합니다.
예를 들어, z가 현재 내용이 "시작"인 문자열 버퍼 객체를 참조하면, 메소드는 z.append ( "le")를 호출하면 문자열 버퍼가 "starkle"을 포함하는 반면 z.insert (4, "le")는 문자열 버퍼를 "스타 렛"을 포함하도록 변경합니다.
일반적으로 SB가 StringBuffer 인스턴스를 참조하면 SB.Append (X)가 SB.Insert (sb.length (),
소스 시퀀스 (예 : 소스 시퀀스에서 추가 또는 삽입)와 관련된 작업이 발생할 때 마다이 클래스는 소스가 아닌 작업을 수행하는 스트링 버퍼에서만 동기화됩니다. StringBuffer는 여러 스레드에서 동시에 사용하도록 안전하도록 설계되었지만 생성자 또는 부록 또는 삽입 작업에 스레드를 통해 공유되는 소스 시퀀스가 전달되면 호출 코드는 작업 시간에 대한 소스 시퀀스의 일관되고 변경되지 않도록해야합니다. 이는 운영 통화 중에 잠금을 잡고 불변의 소스 시퀀스를 사용하거나 스레드에서 소스 시퀀스를 공유하지 않음으로써 발신자가 만족할 수 있습니다.
모든 문자열 버퍼에는 용량이 있습니다. 스트링 버퍼에 포함 된 문자 시퀀스의 길이가 용량을 초과하지 않는 한, 새로운 내부 버퍼 배열을 할당 할 필요는 없습니다. 내부 버퍼가 오버플로되면 자동으로 더 커집니다.
달리 명시되지 않는 한,이 클래스의 생성자 또는 방법에 널 인수를 전달하면 NullPointerException이 발생하게됩니다.
릴리스 JDK 5 에서이 클래스에는 단일 스레드 StringBuilder가 사용하도록 설계된 동등한 클래스가 보충되었습니다. StringBuilder 클래스는 일반적으로 동일한 작업을 모두 지원하므로 동기화를 수행하지 않기 때문에 더 빠릅니다.
부터:
JDK1.0
작가:
아서 반 호프
또한 참조 :
java.lang.stringBuilder
java.lang.string
Javadoc 요약
위에서 볼 수 있습니다.
StringBuffer와 StringBuilder는 모두 가변 문자열로 간주 될 수 있습니다.
StringBuffer는 스레드 안전이며 먼저 나타나며 JDK1.0에서 사용할 수 있습니다.
StringBuilder는 스레드가 아닌 안전이며 나중에 나타나며 JDK1.5에만 존재합니다.
둘의 인터페이스는 정확히 동일하며 StringBuilder가 더 빠릅니다.
실제로, 정상적으로 사용하는 것이 좋고, 이러한 점을 알고 있지만, 소스 코드에서 어떻게 구현되는지를보고 싶습니다.
소스 코드
스레드 안전성을 달성하는 방법
소스 코드에서 모두 추상 클래스 AbstractStringBuilder를 상속받는 것을 볼 수 있습니다.
공개 최종 클래스 StringBuffer Extends AbstractStringBuilder는 Java.io를 구현합니다 .Serializable, charSequencepublic Final Class StringBuilder Extends AbstractStringBuilder 구현 java.io.serializable, charevestence
코드의 양은 크게 크지 않으며 StringBuilder440 코드 줄, StringBuffer718 코드 라인이며, 대부분은 AbstractStringBuilder이며 총 1440 줄의 코드입니다.
몇 가지 관점에서, 우리는 코드를 살펴보고, 하나는 일부 주요 내부 구조물이며, 다른 하나는 일반적으로 사용하는 기능이 구현되는 방식입니다. 문자열은 불변이기 때문에 상수 수영장에 배치됩니다. StringBuilder와 StringBuffer는 숯 배열을 사용하여 구현해야한다고 추측합니다.
/*** 값은 문자 저장에 사용됩니다. */ char [] 값; /*** 카운트는 사용 된 문자 수입니다. */ int count;
데이터는 값으로 저장되고 길이는 카운트로 표시된다는 것을 알 수 있습니다.
몇 가지 공통 방법의 다양한 구현을 봅시다.
StringBuffer
@override public synchronized stringbuffer append (string str) {tostringcache = null; Super.Append (str); 이것을 반환하십시오; } / ** * @Throws strows strows strows indexOutOfBoundSexception {@InheritDoc} * / @override public synchronized stringbuffer insert (int offset, string str) {toStringCache = null; super.insert (오프셋, str); 이것을 반환하십시오; } @override public synchronized string toString () {if (tostringCache == null) {toStringCache = arrays.copyOfRange (value, 0, count); } 새 문자열을 반환합니다 (TostringCache, True); }StringBuilder
@override public StringBuilder Append (String Str) {super.append (str); 이것을 반환하십시오; } / ** * @throws strows strows stringIndExOutOfBoundSexception {@InheritDoc} * / @override public StringBuilder Insert (int 오프셋, String) {super.insert (오프셋, str); 이것을 반환하십시오; } @override public string toString () {// 사본 생성, 배열을 공유하지 마십시오. 새 문자열 (value, 0, count); }코드에서 볼 수 있듯이 대부분의 경우 Strinbbuffer는 스레드 안전을 보장하기 위해 동기화 된 키워드를 추가합니다. 그러나 Tostring 방법은 다르므로 나중에 이것에 대해 이야기하겠습니다.
크기를 초기화하고 성장하는 방법
실제로 배열이기 때문에 배열의 크기 및 성장 방법은 매우 중요합니다. 코드를 살펴 보겠습니다.
/** * 문자가없는 문자열 버퍼와 16 자의 초기 용량을 구성합니다. */ public StringBuffer () {super (16); } /** * 문자가없는 문자열 빌더를 구성합니다. * 초기 용량은 16 자입니다. */ public StringBuilder () {super (16); }보시다시피,이 두 기본 생성자는 모두 기본 배열 크기가 16임을 나타냅니다.
왜 16? 이해하지 못했습니다.
성장 방법에 대해 걱정하는 것은 무엇입니까? Append의 구현을 살펴 보겠습니다
public acpractStringBuilder Append (String Str) {if (str == null) return accendnull (); int len = str.length (); ensurecapacity internal (count + len); str.getchars (0, len, 값, 카운트); count += len; 이것을 반환하십시오; } /** *이 방법은 EnseRecApacity와 동일한 계약을 가지고 있지만 * 동기화되지 않습니다. */ private void ensureCapacityInternal (int minimumCapacity) {// 오버 플로우에 민감한 코드 if (minimumCapacity -value.length> 0) expandCapacity (최소 capacity); } /** * 이것은 * 크기 확인 또는 동기화가없는 ensurecapacity의 확장 시맨틱을 구현합니다. */ void expandCapicacity (int minimumCapacity) {int newCapacity = value.length * 2 + 2; if (newCapacity -MinimumCapacity <0) newCapacity = MinimumCapacity; if (newCapacity <0) {if (minimumCapacity <0) // 오버플로가 새로운 outofMemoryError (); newCapacity = integer.max_value; } value = arrays.copyof (value, newCapacity); }위의 세 가지 방법은 용량을 확장하는 방법을 설명합니다.
전류 용량 *2+2를 넣으십시오
새로 추가 된 길이 가이 값보다 크면 새로 부가가치로 설정하십시오.
오버 플로우가 있으면 memoryError를 던지십시오
StringBuffer에서 Tostring의 구현
/*** Tostring이 반환 한 마지막 값의 캐시. stringbuffer가 수정 될 때마다 지워 져 있습니다. */ 개인 과도 char [] tostringcache; @override public synchronized stringbuffer append (string str) {tostringcache = null; Super.Append (str); 이것을 반환하십시오; } @override public synchronized string toString () {if (tostringCache == null) {toStringCache = arrays.copyOfRange (value, 0, count); } 새 문자열을 반환합니다 (TostringCache, True); }보시다시피, 배열 TostringCache가 정의됩니다. 데이터가 변경 될 때마다 NULL로 설정됩니다. Tostring은 현재 데이터에서 다시 가져옵니다.
과도 키워드는이 배열이 직렬화되는 것을 방지하는 것입니다.
요약
실제로 Java 자체의 소스 코드는 비교적 간단합니다. 소스 코드로 시작할 수 있다면 많은 원칙을 더 깊이 이해할 수 있습니다. 이 기사는 단순히 일부 소스 코드를 나열하고 StringBuffer와 StringBuilder의 유사점과 차이점을 간략하게 설명합니다. 관심있는 친구들은 스스로 볼 수 있습니다.
위의 기사는 소스 코드 관점 (포괄적 인 분석)의 StringBuilder와 StringBuffer의 유사점과 차이점을 간략하게 살펴 봅니다. 나는 그것이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.