Java提供了String、StringBuffer和StringBuilder类来封装字符串,并提供了一系列操作字符串对象的方法。本文主要讲解StringBuilder类的简单使用及其优点。
StringBuilder类
StringBuffer与StringBuilder都继承自AbstractStringBuilder类
1.首先了解StringBuilde与StringBuffer与string的区别
*
是否可变
- String类是一个不可变类,即创建String对象后,该对象中的字符串是不可改变的,直到这个对象被销毁。
- StringBuffer与StringBuilder都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,是可变类
初始化
1.当创建String对象时,可以利用构造方法String str = new String
也可以直接用赋值的方式String s = "Java"来初始化
2.而StringBuilder只能使用构造方法StringBuilder = new StringBuilder(“hello”)的方式初始化。
快慢速度与安全
1.String 有final表示不能被继承 线程不安全的 会产生额外的垃圾!
2.StringBuilder 有final表示不能被继承 成员函数没有synchronized修饰 无同步锁
3.StringBuffer 有final表示不能被继承 成员函数都有synchronized修饰 同步锁
- [StringBuilder是线程不安全的->没加锁(同步锁) 单线程 效率会更高
- [ StringBuffer是线程安全的->加锁(同步锁) 多线程 效率会更低
- [ ]
缓存与清理
String产生的垃圾主要集中在 方法区(字符串常量池)
SB产生的垃圾主要集中在 堆内存
【JVM告诉你,GC(垃圾收集器)在堆内存中活跃程度 比在方法区的活跃程度 要大的大的大的多!】
也就意味着 GC在堆内存中回收垃圾的效率要远远比在方法区高
StringBuilder常用方法及部分源码
追加
public StringBuilder append(char[] str, int offset, int len) {...}
public StringBuilder append(boolean b) {...}
public StringBuilder append(char c)
super.append(c);//调用父类AbstractStringBuilder的方法
return this; //返回当前对象
//针对追加对象的不同有不同的实现方法和实现逻辑
}
@Override
/* //char的实现要进行数组扩容
public AbstractStringBuilder append(char c) {
ensureCapacityInternal(count + 1);
value[count++] = c;
return this;
}
*/
插入:插入需要先进行入参判断为了保障高效插入使用jni方法进行数组复制(system.arraycopy)
@Override
public StringBuilder insert(int offset, Object obj) {
super.insert(offset, obj);//调用父类的
return this;
}
//父类的实现
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);//进行复制
str.getChars(value, offset);
count += len;
return this;//扩容后返回当前对象
}
tostring
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);
}
/**
* readObject is called to restore the state of the StringBuffer from
* a stream.
*/
private void readObject(java.io.ObjectInputStream s)//反序列化
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
count = s.readInt();
value = (char[]) s.readObject();
}
public class StringBuildeDemo01 {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append(10); //追加
sb.append(new Person(30,"老李"));
sb.append("hahalalaxixi");
sb.append(true);
System.out.println(sb.toString());//输出为字符串数组
System.out.println(sb.capacity()); //指的是当前value的容量
System.out.println(sb.length()); //指的是当前value中有效字符的个数
System.out.println(sb.charAt(1));//输出当前角标字母
sb.deleteCharAt(0);//删除角标位置的字
sb.delete(0, 10); //删除[start,end)左闭右开
System.out.println(sb.indexOf("name"));//寻找name若找到返回第一次出现的角标值,否则返回-1。
sb.insert(5, "lala");//从角标5插入lala