Java源码分析六(StringBulider)
Java源码分析六(StringBulider)
继承的类和接口分析
AbstractStringBuilder、Serializable、CharSequence
类中出现的属性
序列号
static final long serialVersionUID = 4383685877147921099L;
构造器
//默认调用父类AbstractStringBuilder 创建一个长度为16的char数组
public StringBuilder() {
super(16);
}
//传入一个字符串父类CharSequence 创建一个seq.length+16的char数组
public StringBuilder(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
//根据你传入的int值 创建一个长度为capacity的char数组
public StringBuilder(int capacity) {
super(capacity);
}
//同上面CharSequence一个原理
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
类中出现的方法
//根据传入的布尔值调用父类的append(boolean b)方法方法使用步骤如下先判断当前count值(char数组存的数值)+“true” or“false”的长度
//4 或5 查询一下是否数组的长度够(如果不够就扩容扩容机制如下)
//父类的扩容方法 默认新数组的长度为原数长度的二倍+2 如果超过int最大值即越界 比较少见基本上没这么长的字符串越界问题就麻烦了 暂时就不说了
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
public StringBuilder append(boolean b) {
super.append(b);
return this;
}
//跟上面类似传入一个字符先判断空间够不够 不够就扩容 原理一样
public StringBuilder append(char c) {
super.append(c);
return this;
}
//先判断空间是否够否则扩容
public StringBuilder append(char[] str) {
super.append(str);
return this;
}
//方法类似 先判断当前数组长度能不能加入len长度数据 如果不能就扩容如果可以就在当前count后
//存入str数组从offset开始len个数据
public StringBuilder append(char[] str, int offset, int len) {
super.append(str, offset, len);
return this;
}
//加个字符串的父类 原理一模一样
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
//跟上面原理一模一样 上面相当于 (s,0,arr.length)
public StringBuilder append(CharSequence s, int start, int end) {
super.append(s, start, end);
return this;
}
//追加一个double
public StringBuilder append(double d) {
super.append(d);
return this;
}
//在后面追加一个float
public StringBuilder append(float f) {
super.append(f);
return this;
}
//添加int值的时候 如果i是int的最小值直接append("-2147483648"); 然后他自己看是否需要扩容 否则根据int值的长度去判断是否需要扩容
public StringBuilder append(int i) {
super.append(i);
return this;
}
//和int类似 先判断是否是long的最小值
public StringBuilder append(long lng) {
super.append(lng);
return this;
}
//传入一个对象 比如传入个Person对象 而且没有重写toString值就会追加一个反射类名+@+hashCode值 然后去判断是否需要扩容
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
//一样的方法
public StringBuilder append(String str) {
super.append(str);
return this;
}
//从StringBuffer中取数据添加
public StringBuilder append(StringBuffer sb) {
super.append(sb);
return this;
}
根据传入的int值去和ASCII解析然后追加 例如你传入65 就会出来A
public StringBuilder appendCodePoint(int codePoint) {
super.appendCodePoint(codePoint);
return this;
}
//删除从start 到end 位置的数据 之前说AbstractStringBuilder说过相当于end之后的数据移动到start位置
public StringBuilder delete(int start, int end) {
super.delete(start, end);
return this;
}
//删除从index到count位置的数据 意思是从index开始后所有的数据删除(好暴力)
public StringBuilder deleteCharAt(int index) {
super.deleteCharAt(index);
return this;
}
//返回str字符串第一次出现的位置 之前String详细讲过 反正最后的源码是指向String
public int indexOf(String str) {
return super.indexOf(str);
}
//从fromIndex开始 str字符串第一次出现的位置
public int indexOf(String str, int fromIndex) {
return super.indexOf(str, fromIndex);
}
//和append 一样区别就在插入的数据是在offset开始查 本来默认是从最后有数据的地方(count)位置 其他一模一样重载方法不写了
public StringBuilder insert(int offset, boolean b) {
super.insert(offset, b);
return this;
}
//最后一次出现str的索引值
public int lastIndexOf(String str) {
return super.lastIndexOf(str);
}
//从formIndex开始 最后一次出现str的索引位置
public int lastIndexOf(String str, int fromIndex) {
return super.lastIndexOf(str, fromIndex);
}
//私有方法 通过readObject()方法,读取之前保存的变量。readObject的原始定义是在ObjectInputStream.java中
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
count = s.readInt();
value = (char[]) s.readObject();
}
//将start到end位置上数据替换成str 中间设计扩容问题
public StringBuilder replace(int start, int end, String str) {
super.replace(start, end, str);
return this;
}
//将字符串反转 相当于两边数据交换//这个原理很神奇 当时说父类的时候说过 很神奇!!!从中间断开两端慢慢交换数据
//我一开始想的是最后第一个和最后一个交换然后同时往中间走 其实也差不多
public StringBuilder reverse() {
super.reverse();
return this;
}
//将cahr中的数据从0到count返回
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
//网络编程时序列化用的
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
s.writeInt(count);
s.writeObject(value);
}
StringBuilder与String异同
String 中的char数组是不可变 每次String属性的变更都会创建新的对象如果以newString(String s) 格式新建
如果用等号 会去常量池寻找有没有相同的 如果没有也是创建 比较耗费空间
StringBuilder中的数组是可变的 你可以通过append 无限叠加 如果字符串的长度不够他会扩容扩容原理当前数组长度向左移一位+2
如果你想存储一个超级长的字符串推荐你第一次就吧大改长度给他传过去 不然频繁的扩容也不太好