概述
该文档主要从源码角度学习
CharSequence
及相关内容(如SpannableString
、SpannableStringBuilder
、String
、StringBuilder
、StringBuffer
等)的组织结构和实现
具体的组织结构可查看下图
基础接口
CharSequence
- 描述
char
类型值的只读序列- 提供统一的只读的访问方法,如长度、某位置的值、子序列的获取等
hashCode()
和equals()
方法使用注意:并未重写Object
的hashCode()
和equals()
方法,因此无法对实现CharSequenc
的类进行比较;同时每个对象可以被不同的类实现,无法保证每个类可以测试相互之间实例的等同性,所以不适合使用任意的CharSequence
实例作为set
的元素或map
的键值
- 具体方法
Method | Description |
---|---|
int length() | 返回字符序列的长度 |
char charAt(int index) | 返回指定位置处([0, length()-1] )的char 类型值 |
CharSequence subSequence(int start, int end) | 返回指定范围([start, end) ]的字符序列 |
String toString() | 返回和这个序列相同的String 类型值 |
IntStream chars() | 默认方法(Java8 才支持);返回这个序列char 类型对应的int 类型值的流 |
IntStream codePoints() | 默认方法(Java8 才支持);返回这个序列的code point 值的流 |
Appendable
- 描述
- 可以追加
char
序列和值 - 若某实例想要接收
Formatter
格式化的输出,必须要实现Appendable
接口 - 追加的字符应该是有效的
Unicode
字符;注意增补字符可能由多个16位char
值组成 Appendable
对于多线程访问没必要是安全的,线程安全是继承或实现该接口的类的责任- 因为此接口可能由具有不同的错误处理风格的类实现,所以无法保证错误会传递给调用者
- 可以追加
- 具体方法
Method | Description |
---|---|
Appendable append(CharSequence csq) | 追加指定的字符序列;依赖于实现字符序列csq 的类,全部的序列可能不被追加,如java.nio.CharBuffer 由缓存的位置和限制数决定;若csq 为null ,四个字符“null” 会被追加 |
Appendable append(CharSequence csq, int start, int end) | 追加指定字符序列位置处([start, end) )的内容 ;若csq 为null ,四个字符“null” 会被追加 |
Appendable append(char c) | 追加指定的字符 |
Serializable
描述
Java
提供了一种对象序列化的机制,即对象可以表示成字节序列(或字节流),包括对象的数据、对象的类型信息和存储在对象中的数据类型- 标记接口,没有方法或域
- 没有实现该接口的类不会让任一个状态序列化或反序列化;序列化类的所有子类型都是可序列化的
- 为允许非序列化类的子类型序列化,子类型可以承担保存和恢复父类型的
public
、protected
和package
(如果可能的话)域的责任;子类型只有在继承类有可访问的无参构造函数初始化类的状态时,可以承担此责任 - 反序列化期间,非序列化类的域会使用
public
或protected
的无参构造函数初始化 static
或transient
修饰的数据成员不可被序列化- 数组或集合中的序列化:要求数组中的所有对象或集合中的所有元素必须是可序列化的
使用
ObjectOutputStream
:用于写基本的数据类型和Java
对象到一个OutputStream
;注意只有支持java.io.Serializable
接口的对象可以被写入流
Method | Description |
---|---|
ObjectOutputStream(OutputStream out) | 创建一个写到指定输出流的ObjectOutputStream |
final void writeObject(Object obj) | 写指定的对象到ObjectOutputStream |
void flush() | 冲刷当前的输出流 |
void close() | 关闭当前的输出流 |
ObjectInputStream
:用于反序列化使用ObjectOutputStream
写入的基本数据和对象
Method | Description |
---|---|
ObjectInputStream(InputStream in) | 创建一个从指定的输入流读取的ObjectInputStream |
final Object readObject() | 从输入流中读取一个对象 |
void close() | 关闭当前的输入流 |
注意
- 如果一个序列化类没有显示定义一个
serialVersionUID
,然后序列化运行时会根据这个类的多方面因素(正如Java
对象序列化规范里描述的那样)计算一个默认的serialVersionUID
值 - 然而强烈推荐所有的序列化类显示定义
serialVersionUID
值,因为默认的serialVersionUID
计算是对可能随编译器实现变化的类的详情高度敏感的,因此在反序列化期间可能导致不可预料的InvalidClassException
- 强烈建议显示的
serialVersionUID
定义尽可能使用private
修饰,因为这样的只用在立即定义的类的serialVersionUID
的域上的定义不能作为继承的成员使用 - 数组类不能定义一个显示的
serialVersionUID
,所以数组只有默认的计算值 serialVersionUID
计算的Android
实现会在android N
上随着一些类轻微变化,为了保证兼容性,极力推荐使用显示的serialVersionUID
域来避免兼容性问题
Comparable
- 描述
- 此接口强加全部的排序在实现该接口的每个类对象上;这种排序被称为
自然排序
,这个类的compareTo()
方法被称为自然排序方法 - 实现该接口的对象列表或数组可以通过
Collections.sort()
或Arrays.sort()
方法自动排序 - 实现此接口的对象可以被用作
排序map
的键值或排序set
的元素,没有必要指定一个comparator
- 一个类的自然排序和
equals()
方法的一致性:有且仅有当compareTo()
方法等于0
,并且equals()
方法等于true
的时候;在排序map
或排序set
中强烈推荐;实际上所有实现了Comparable
接口的Java
核心类都有和equals()
一致的自然排序 null
不是一个类,也不是一个对象,compareTo(null)
方法会抛出NullPointerException
,尽管equals(null)
返回false
- 此接口强加全部的排序在实现该接口的每个类对象上;这种排序被称为
- 方法
Method | Description |
---|---|
int compareTo(T o) | 和指定的对象进行比较;负数表示小于,0表示等于,正数表示大于 |
具体接口或类
CharSequence衍生
GetChars
- 描述
- 用途:若
CharSequence
的实现类有getChars()
方法,可以实现该接口 - 作用:比多次调用
charAt()
方法快得多
- 用途:若
- 具体方法
Method | Description |
---|---|
void getChars(int start, int end, char[] dest, int destoff) | 将给定位置处([start, end) )的内容拷贝到给定的数组dest 中,其中起始位置是destoff |
AlteredCharSequence
- 描述
- 一个变化的
CharSequence
主要是另一个CharSequence
的镜像,除了指定范围的字符是不同的字符数组的镜像
- 一个变化的
public static AlteredCharSequence make(CharSequence source, char[] sub, int substart, int subend):创建一个变化的
CharSequence
,其文本(可能是spans
)来自于source
,除了指定范围([substart, subend)
)处是sub
的偏移量为0
的镜像123456public static AlteredCharSequence make(CharSequence source, char[] sub, int substart, int subend) {if (source instanceof Spanned)return new AlteredSpanned(source, sub, substart, subend);elsereturn new AlteredCharSequence(source, sub, substart, subend);}public char charAt(int off):获取指定位置处的字符,注意
off
和指定字符数组提供区间[start, end)
的关系123456public char charAt(int off) {if (off >= mStart && off < mEnd) // 获取指定字符数组sub区间内的字符return mChars[off - mStart];else // 获取指定CharSequence的off位置处的字符return mSource.charAt(off);}public void getChars(int start, int end, char[] dest, int off):从
mSource
中拷贝[start, end)
范围的内容到dest
中,注意拷贝区间和原始变化区间[mStart, mEnd)
的关系处理12345678910public void getChars(int start, int end, char[] dest, int off) {TextUtils.getChars(mSource, start, end, dest, off); // 由mSource决定拷贝[start, end)位置处的字符到偏移量为off的dest中// 着重处理mChars内的拷贝:获取最大的start和最小的end,使拷贝区间尽量在[mStart, mEnd)内,便于拷贝mChars的内容到dest中start = Math.max(mStart, start);end = Math.min(mEnd, end);if (start > end)System.arraycopy(mChars, start - mStart, dest, off, end - start);}TextUtils.getChars(CharSequence s, int start, int end, char[] dest, int destoff):依次判断
s
是否为String
、StringBuffer
、StringBuilder
、GetChars
的实例,若是,调用对应的getChars()
方法即可;若不是,将[start, end)
位置处的字符拷贝到偏移量为destoff
的dest
中12345678910111213141516public static void getChars(CharSequence s, int start, int end, char[] dest, int destoff) {Class<? extends CharSequence> c = s.getClass();if (c == String.class)((String) s).getChars(start, end, dest, destoff);else if (c == StringBuffer.class)((StringBuffer) s).getChars(start, end, dest, destoff);else if (c == StringBuilder.class)((StringBuilder) s).getChars(start, end, dest, destoff);else if (s instanceof GetChars)((GetChars) s).getChars(start, end, dest, destoff);else {for (int i = start; i < end; i++)dest[destoff++] = s.charAt(i);}}
AlteredCharSequence.AlteredSpanned
定义在AlteredCharSequence
中,Spanned
的实现类,在AlteredCharSequence
的基础上附加了Spanned
的相关功能
Spanned系列
Spanned
- 描述
- 用于让标记对象绑定到文本的某范围的文本的接口;并不是所有的类都有可变的标记或文本
- 具体方法
Method | Description |
---|---|
返回一个绑定指定类型的CharSequence 或其子类的切片的标记对象数组;也可直接指定Object.class ,不管任何类型 |
|
int getSpanStart(Object tag) | 返回指定标记对象绑定的文本范围的开始位置;若对象没有绑定,返回-1 |
int getSpanEnd(Object tag) | 返回指定标记对象绑定的文本范围的结束位置;若对象没有绑定,返回-1 |
int getSpanFlags(Object tag) | 返回当使用Spannable.setSpan 绑定指定的标记对象时指定的flags ,若指定的对象未被绑定,这里返回0 |
int nextSpanTransition(int start, int limit, Class type) | 返回第一个大于type 类型标记对象开始或结束处的给定的start 值,否则如果没有开始或结束值比给定的start 值大,但是小于给定的limit ,则返回该limit ;可直接指定null 或Object.class ,不管任何类型 |
SpannableStringInternal
- 描述
- 对
SpannedString
和SpannableString
的抽象封装而成
- 对
- 待补充
SpannedString
- 描述
- 文本的内容和标记对象都是不可变的
public CharSequence subSequence(int start, int end):根据给定的
[start, end]
范围获取SpannedString
实例123public CharSequence subSequence(int start, int end) {return new SpannedString(this, start, end);}public static SpannedString valueOf(CharSequence source):根据给定的
CharSequence
类型获取SpannedString
实例1234567public static SpannedString valueOf(CharSequence source) {if (source instanceof SpannedString) {return (SpannedString) source;} else {return new SpannedString(source);}}
Spannable
- 描述
- 用于标记对象可以绑定和解绑的文本的接口;并不是所有的类都有可变的文本,如
Editable
- 用于标记对象可以绑定和解绑的文本的接口;并不是所有的类都有可变的文本,如
- 具体方法
Method | Description |
---|---|
void setSpan(Object what, int start, int end, int flags) | 绑定指定的标记对象到文本的[start, end] 范围处,或若标记对象已绑定了,则移除对应范围内的标记对象 |
void removeSpan(Object what) | 从指定标记对象绑定的文本范围内移除该标记对象;第一次移除从未绑定的标记对象总是可行的 |
Spannable.Factory
- 描述
- 用于
TextView
创建Spannable
实例 - 可以通过继承该类实现除
SpannableString
的其它类
- 用于
- 具体方法
Method | Description |
---|---|
static Spannable.Factory getInstance() | 返回标准的Spannable 工厂实例 |
Spannable newSpannable(CharSequence source) | 根据给定的CharSequence 提供SpannableString 实例;可以重写该方法提供其它的Spannable 类型 |
SpannableString
- 描述
- 文本的内容是不可变的,文本的标记对象是可以绑定和解绑的
public CharSequence subSequence(int start, int end):根据给定的
[start, end]
范围获取SpannableString
实例123public CharSequence subSequence(int start, int end) {return new SpannableString(this, start, end);}public static SpannableString valueOf(CharSequence source):根据给定的
CharSequence
类型获取SpannableString
实例1234567public static SpannableString valueOf(CharSequence source) {if (source instanceof SpannableString) {return (SpannableString) source;} else {return new SpannableString(source);}}注意:提供了公共的
setSpan()
和removeSpan()
方法用于绑定和解绑标记对象
Editable
- 描述
- 文本的内容和标记对象均可变化,与
String
不可变的文本形成对比
- 文本的内容和标记对象均可变化,与
- 具体方法
Method | Description |
---|---|
Editable replace(int st, int en, CharSequence source, int start, int end) | 用给定source 的start... end 范围内的文本拷贝来替换该Editable 中指定st...en 范围的文本。当目标片段为空时,该方法表示插入操作;或源片段为空时,该方法表示删除操作。在变化发送之前,使用setFilters(InputFilter[]) 方法设置的过滤器可以帮助修改source 的文本 |
Editable replace(int st, int en, CharSequence text) | 等同于replace(st, en, text, 0, text.length()) |
Editable insert(int where, CharSequence text, int start, int end) | 等同于replace(where, where, text, start, end) |
Editable insert(int where, CharSequence text) | 等同于replace(where, where, text, 0, text.length()) |
Editable delete(int st, int en) | 等同于replace(st, en, "", 0, 0) |
Editable append(CharSequence text) | 等同于replace(length(), length(), text, 0, text.length()) |
Editable append(CharSequence text, int start, int end) | 等同于replace(length(), length(), text, start, end) |
Editable append(char text) | 等同于append(String.valueOf(text)) |
void clear() | 等同于replace(0, length(), "", 0, 0) ,注意该方法只清除文本,并不是spans |
void clearSpans() | 移除该Editable 的所有spans |
void setFilters(InputFilter[] filters) | 设置一系列无论何时该Editable 的文本变化时会成功调用的过滤器,每个过滤器可以限制或变换被插入的文本 |
InputFilter[] getFilters() | 返回当前应用于该Editable 的过滤器数组 |
Editable.Factory
- 描述
- 用于
TextView
创建Editable
实例 - 可以通过继承该类实现除
SpannableStringBuilder
的其它类
- 用于
- 具体方法
Method | Description |
---|---|
static Editable.Factory getInstance() | 返回标准的Editable 实例 |
Editable newEditable(CharSequence source) | 根据给定的CharSequence 创建SpannableStringBuilder 实例 |
GraphicsOperations
- 描述
- 如果
CharSequence
能够做快速的绘制、测量、宽度计算,可以实现该接口 - 其方法和
Canvas
、Paint
的方法类似
- 如果
SpannableStringBuilder
- 描述
- 文本的内容和标记对象都是可变的
- 待补充
String系列
String
- 描述
Java
程序中所有字符串字面量,如“abc”
作为String
类的实例实现- 字符串是常量,创建后不能被修改
String
包含有比较、搜索、提取子字符串、转换为大写或小写的字符串拷贝等方法- 支持字符串拼接(
+
)操作,方便其它对象转换为字符串;通过StringBuilder
或StringBuffer
类和它们的append()
方法实现字符串拼接;通过对象的toString()
(由Object
定义,其子类重写)方法实现转换 - 传递
null
参数给String
的构造函数或方法会抛出NullPointerException
String
代表了增补的字符由代理对来表示的UTF-16
格式的字符串,指数值引用了char
的代码单位,所以在一个字符串中一个增补的字符使用了两个位置String
提供了处理Unicode
代码点(如character
类型)的方法,除了处理Unicode
代码单元(如char
类型值)
AbstractStringBuilder
- 描述
- 可变的字符序列
StringBuilder
或StringBuffer
类的抽象类- 通过某些调用方法可以修改序列的长度和内容
- 传递
null
参数给构造函数或方法会抛出NullPointerException
public void ensureCapacity(int minimumCapacity):确保容量至少等于提供的最小值。如果当前容量小于提供的最小值,一个新的内部数组会使用新的容量进行分配,其中新的容量是提供的最小值和当前容量的2倍再加2的值中的更大的一个
1234public void ensureCapacity(int minimumCapacity) {if (minimumCapacity > 0) // 只有在提供参数大于0时才可实现容量扩大操作ensureCapacityInternal(minimumCapacity);}private void ensureCapacityInternal(int minimumCapacity):比较提供的最小容量和内部数组的长度,若大于0,根据提供的最小容量扩大内部的容量,否则什么也不做
12345private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0) // 提供参数大于内部数组长度时才可实现容量扩大操作expandCapacity(minimumCapacity);}void expandCapacity(int minimumCapacity):实现容量扩大,并完成字符串的拷贝。注意当计算并比较后的最大容量小于0,也就是溢出,并且提供的最小容量值也小于0时,会抛出内存溢出异常
1234567891011121314void expandCapacity(int minimumCapacity) {int newCapacity = value.length * 2 + 2;if (newCapacity - minimumCapacity < 0) // 在当前容量基础上扩大后的容量值仍小于提供的最小容量值newCapacity = minimumCapacity;if (newCapacity < 0) { // 经比较后的新容量值溢出时// 若提供的最小容量值小于0,会直接抛出内存溢出异常if (minimumCapacity < 0) // overflowthrow new OutOfMemoryError();// 否则设置新容量为最大整型值newCapacity = Integer.MAX_VALUE;}// 拷贝内部数组[0,Math.min(count, newCapacity))区间的内容value = Arrays.copyOf(value, newCapacity);}public void setLength(int newLength):设置字符序列的长度为提供的参数。若提供的长度小于当前的长度,该字符序列的长度变为提供的长度;若提供的长度大于当前的长度,追加额外的空字符(
‘\0’
)以便该字符序列的长度变为提供的长度1234567891011public void setLength(int newLength) {if (newLength < 0) // 提供的长度不准小于0throw new StringIndexOutOfBoundsException(newLength);ensureCapacityInternal(newLength); // 完成原有内部容量的扩大操作// 若内部内容长度小于提供的参数时,填充‘\0‘到内部数组的[count, newLength)区间处if (count < newLength) {Arrays.fill(value, count, newLength, '\0');}// 设置该字符序列的内容长度为提供的长度count = newLength;}public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):拷贝字符序列
[srcBegin, srcEnd)
位置处的内容到提供的dst
数组中的偏移量destBegin
处。注意拷贝之前对提供参数所进行的严格判断(提供指数超过数组界线异常问题)1234567891011public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin){if (srcBegin < 0) // 拷贝的起始位置不能小于0throw new StringIndexOutOfBoundsException(srcBegin);if ((srcEnd < 0) || (srcEnd > count)) // 拷贝的结束位置不能小于0 或者 拷贝的结束为止不能大于内部内容长度throw new StringIndexOutOfBoundsException(srcEnd);if (srcBegin > srcEnd) // 拷贝的起始位置不能大于结束位置throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");// 拷贝内部数组[srcBegin, srcEnd)区间处的内容到数组dst的[dstBegin, dstBegin+srcBegin-srcEnd)区间处System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);}public AbstractStringBuilder append(String str):追加提供的字符串到该字符序列。若提供的
str
为null
,追加“null”
内容。注意追加内容后会根据提供内容的长度来增加该字符序列的长度,所以需要完成相应的容量扩大和内容长度设置操作123456789public AbstractStringBuilder append(String str) {if (str == null) // 追加“null”内容return appendNull();int len = str.length();ensureCapacityInternal(count + len); // 完成原有内部容量的扩大操作str.getChars(0, len, value, count); // 拷贝str内容到内部数组的[count, count+len)区间处count += len; // 在原有内容长度基础上增加提供内容的长度return this;}private AbstractStringBuilder appendNull():完成
“null”
内容的追加操作123456789101112private AbstractStringBuilder appendNull() {int c = count;ensureCapacityInternal(c + 4); // 完成原有内部容量的扩大操作final char[] value = this.value;// 在原有内部数组基础上追加内容,注意指数的自加操作的安全性(因为在内部容量扩大的基础上)value[c++] = 'n';value[c++] = 'u';value[c++] = 'l';value[c++] = 'l';count = c;return this;}public AbstractStringBuilder delete(int start, int end):移除该字符序列
[start, end)
位置处的内容1234567891011121314public AbstractStringBuilder delete(int start, int end) {if (start < 0) // 起始位置不能小于0throw new StringIndexOutOfBoundsException(start);if (end > count) // 保证结束位置的有效性(比较提供的结束位置和内部内容的长度)end = count;if (start > end) // 起始位置不能大于结束位置throw new StringIndexOutOfBoundsException();int len = end - start;if (len > 0) { // 移除合理的区间[start, end)处的内容,注意内部内容长度的设置操作(减少了len的长度)System.arraycopy(value, start+len, value, start, count-end);count -= len;}return this;}public AbstractStringBuilder replace(int start, int end, String str):使用提供的字符串
str
来替换该字符序列的给定区间[start, end)
处的字符12345678910111213141516171819public AbstractStringBuilder replace(int start, int end, String str) {if (start < 0) // 起始位置不能小于0throw new StringIndexOutOfBoundsException(start);if (start > count) // 起始位置不能大于内部内容长度throw new StringIndexOutOfBoundsException("start > length()");if (start > end) // 起始位置不能大于结束位置throw new StringIndexOutOfBoundsException("start > end");if (end > count) // 结束位置大于内部内容长度时,修改结束位置为内部内容最后位置处end = count;int len = str.length();int newCount = count + len - (end - start);ensureCapacityInternal(newCount); // 变换原有内部容量操作// 直接拷贝内部数组[end, count)区间处的内容到扩大后的内部容量的[start+len, newCount)区间处System.arraycopy(value, end, value, start + len, count - end);str.getChars(value, start); // 直接拷贝str到[start, start+len)区间处count = newCount;return this;}public String substring(int start, int end):创建提供
[start, end)
区间参数处的字符序列的字符串123456789public String substring(int start, int end) {if (start < 0) // 起始位置不能小于0throw new StringIndexOutOfBoundsException(start);if (end > count) // 结束位置不能大于内部内容长度throw new StringIndexOutOfBoundsException(end);if (start > end) // 起始位置不能大于结束位置throw new StringIndexOutOfBoundsException(end - start);return new String(value, start, end - start); // 创建由[start, end)区间处的字符序列组成的字符串}public AbstractStringBuilder insert(int index, char[] str, int offset, int len):将提供的数组
str
偏移量offset
开始len
长度的内容插入到该字符序列的index
位置处1234567891011121314151617public AbstractStringBuilder insert(int index, char[] str, int offset, int len){if ((index < 0) || (index > length())) // 插入位置不能小于0 或者 大于内部容量throw new StringIndexOutOfBoundsException(index);// 拷贝的偏移量不能小于0 或者 拷贝内容的长度不能小于0 或者 拷贝的偏移量不能大于所拷贝内容的长度与欲拷贝的长度差值if ((offset < 0) || (len < 0) || (offset > str.length - len))throw new StringIndexOutOfBoundsException("offset " + offset + ", len " + len + ", str.length "+ str.length);ensureCapacityInternal(count + len); // 完成扩大内部容量操作// 拷贝内部数组[index, count)区间处的内容到[index+len, count+len)区间处System.arraycopy(value, index, value, index + len, count - index);// 拷贝数组str[offset, len)区间处的内容到内部数组[index, index+len)区间处System.arraycopy(str, offset, value, index, len);count += len; // 在原有内部内容长度基础上增加插入内容长度return this;}public AbstractStringBuilder insert(int offset, String str):将提供的字符串
str
插入到该字符序列的offset
位置处12345678910111213public AbstractStringBuilder insert(int offset, String str) {if ((offset < 0) || (offset > length())) // 偏移量不能小于0 或者 不能大于内部容量throw new StringIndexOutOfBoundsException(offset);if (str == null) // 若提供参数为null,插入“null”字符串str = "null";int len = str.length();ensureCapacityInternal(count + len); // 完成扩大内部容量操作// 拷贝内部数组[offset, count)区间处的内容到[offset+len, count+len)区间处System.arraycopy(value, offset, value, offset + len, count - offset);str.getChars(value, offset); // 拷贝提供的字符串到[offset, offset+len)区间处count += len;return this;}public AbstractStringBuilder reverse():待补充
StringBuilder
- 描述
- 可变的字符序列
- 兼容
StringBuffer
,但不能保证同步 - 该类被设计用于字符串缓存在单线程使用时用于
StringBuffer
的混乱信息替换 - 该类相对于
StringBuffer
被推荐使用,因为其大多情况下更快 - 重载
append
、insert
等方法,支持任意类型数据 StringBulder
实例在多线程场景中不安全
- public String toString():重写
toString()
方法12345public String toString() {// Create a copy, don't share the arrayreturn new String(value, 0, count);}
StringBuffer
- 描述
- 线程安全、可变的字符序列
- 可通过某些方法调用实现字符序列长度和内容的修改
- 重载
append
、insert
等方法,支持任意类型数据
toStringCache:
transient
变量,用于缓存toString()
方法拷贝的该类的内部数组,当被修改时会被清空12345/*** A cache of the last value returned by toString. Cleared* whenever the StringBuffer is modified.*/private transient char[] toStringCache;public synchronized String toString():重写
toString()
方法1234567public synchronized String toString() {if (toStringCache == null) {toStringCache = Arrays.copyOfRange(value, 0, count);}return new String(toStringCache, true);}