Java 7のベースタイプ6編-Java可変文字列タイプ
実際のプロジェクト開発では、動的なSQL文のつづりなど、可変文字列を操作する場合が多いかもしれません.
StringBuilderとStringBufferを可変文字列と呼ぶのは、
(1)append()メソッドのような元の文字列を大幅に変更する操作を提供する.変更は元の文字列に基づいて修正され、Stringのいくつかの方法とは異なり、new String()によって新しい文字列が返されます.
(2)文字列は自動的に拡張され,人為的な操作を必要とせず,String自体は拡張を行わない.
この2つのクラスの実装について詳しく説明します.まずAbstractStringBuilderクラスを見てみましょう
多くのappend()メソッドがあり、処理方法は非常に似ており、興味のある人は自分で見ることができます.append()メソッドは末尾でのみ追加できますが、文字列の真ん中を挿入する場合はinsert()メソッドを使用して、例を挙げます.
自動拡張が行われ、str文字列の文字がvalueの指定された位置に挿入されることがわかります.自動的に拡張されるので、可変文字列を使用する場合は、拡張を防止するために十分な容量を指定することが望ましい.下位層は配列のコピーを行う必要があるからです.
テスト手順は次のとおりです.
StringBuilderクラスとStringBufferクラスはこの抽象クラスを実現しているが、StringBufferクラスで公開されている方法にsynchronizedキーワードを加えて同期するのもStringBuilderとの最大の違いである.
CharSequenceは文字シーケンスを表すインタフェースであり、String、StringBuilder、StringBufferはこのインタフェースを実現し、下位層は配列によって実現される.
String、StringBuilder、StringBufferの異同点を前に書いたブログと結びつけて、この3つのよく使われるクラスの異同点を分析します.
異同点: Stringのオブジェクトは可変ではありません.StringBuilderとStringBufferは可変です. StringBuilderはスレッドが安全ではありません.StringBufferはスレッドが安全な です Stringのoffset,value,countはfinalによって修飾された修正不可能である.一方、StringBufferとStringBuilderのvalueでは、countはAbstractStringBuilderクラスから継承され、finalによって修飾されず、実行中に修正可能でoffset変数がないことを示しています.
同じ点:
3つのクラスはfinalで修飾されており、継承できません.いずれも表示文字列を表すことができます(ソースコードではCharSequence.javaクラスが継承されていることがわかります)
StringBuilderとStringBufferを可変文字列と呼ぶのは、
(1)append()メソッドのような元の文字列を大幅に変更する操作を提供する.変更は元の文字列に基づいて修正され、Stringのいくつかの方法とは異なり、new String()によって新しい文字列が返されます.
(2)文字列は自動的に拡張され,人為的な操作を必要とせず,String自体は拡張を行わない.
この2つのクラスの実装について詳しく説明します.まずAbstractStringBuilderクラスを見てみましょう
abstract class AbstractStringBuilder implements Appendable, CharSequence {
//
char[] value;
int count; // The count is the number of characters used.
//
AbstractStringBuilder() { }
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
//
public int capacity() {
return value.length;
}
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);
}
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
void expandCapacity(int minimumCapacity) { // value
int newCapacity = value.length * 2 + 2;// 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);//
}
}
は、上記のように文字配列を定義し、制限はありません.拡張方法といくつかのデフォルトの構築方法も提供されています.クラスはAppendableインタフェースを継承するため、このインタフェースは主にappend()メソッドを定義し、この抽象クラスで実装されています.public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException("start " + start + ", end " + end + ", s.length() " + s.length());
int len = end - start;//
ensureCapacityInternal(count + len); // value
for (int i = start, j = count; i < end; i++, j++) // value
value[j] = s.charAt(i);
count += len;
return this;
}
多くのappend()メソッドがあり、処理方法は非常に似ており、興味のある人は自分で見ることができます.append()メソッドは末尾でのみ追加できますが、文字列の真ん中を挿入する場合はinsert()メソッドを使用して、例を挙げます.
public AbstractStringBuilder insert(int offset, String str) {
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
if (str == null)
str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);// value len
str.getChars(value, offset); // str value
count += len;
return this;
}
自動拡張が行われ、str文字列の文字がvalueの指定された位置に挿入されることがわかります.自動的に拡張されるので、可変文字列を使用する場合は、拡張を防止するために十分な容量を指定することが望ましい.下位層は配列のコピーを行う必要があるからです.
テスト手順は次のとおりです.
StringBuilder str =new StringBuilder("abc");
str.insert(1, "xx");
System.out.println(str.toString());// axxbc
StringBuilderクラスとStringBufferクラスはこの抽象クラスを実現しているが、StringBufferクラスで公開されている方法にsynchronizedキーワードを加えて同期するのもStringBuilderとの最大の違いである.
CharSequenceは文字シーケンスを表すインタフェースであり、String、StringBuilder、StringBufferはこのインタフェースを実現し、下位層は配列によって実現される.
String、StringBuilder、StringBufferの異同点を前に書いたブログと結びつけて、この3つのよく使われるクラスの異同点を分析します.
異同点:
同じ点:
3つのクラスはfinalで修飾されており、継承できません.いずれも表示文字列を表すことができます(ソースコードではCharSequence.javaクラスが継承されていることがわかります)