一. StringBuffer类是final类 , 且它创建的字符串是在堆中创建的:
public static void main(String[] args) {
//1. String类和StringBuffer类都是final类,不能被继承;
//2. 前者创建的对象指向的字符串最终指向的都是常量池中的字符串,
//3. 但是后者继承了AbstractStringBuilder类,这个类中有属性char[] value,不是final;
//4. 该value数组存放字符串内容,说明创建的字符串不会在常量池中建立,而是在堆中建立;
//5.String类的value数组是final,所以每次更改String值都得重新创建地址;
//6. 所以StringBuffer类更改值不用每次重新创建地址(不用每次创建新对象),可以更改内容,效率更高;
StringBuffer stringBuffer=new StringBuffer("hello");
//所以说明这个hello是在堆中创建的,而不是在常量池中;
//char数组空间初始为16,如果长度不够会再自动添加,而记录value长度的length()返回的是里面的count大小
}
二. String类和StringBuffer类的互相转换:
public static void main(String[] args) {
//1. String类-->>StringBuffer类:
String s1=new String("abc");
StringBuffer stringBuffer1=new StringBuffer(s1);
//2.StringBuffer类-->>String类:
//方式1: 使用StringBuffer的toString()方法:
StringBuffer stringBuffer2=new StringBuffer("hello");
String s2=stringBuffer1.toString();
//方式2:使用String的构造器:
String s3=new String(stringBuffer1);
}
三. StringBuffer类的一些常用方法:
public static void main(String[] args) {
StringBuffer s=new StringBuffer("hello");
//增,append会在后面增加各种类型的值都会变成字符串
s.append(','); //"hello,"
s.append("张三丰"); //"hello,张三丰"
s.append("赵敏").append(100).append(true).append(10.5); //"hello张三丰赵敏100true10.5"
System.out.println(s); //会输出最后内容,因为StringBuffer类也重写了toString类
//删
//删除[11,14)的字符:
s.delete(11,14);
System.out.println(s); //"hello,张三丰赵敏true10.5"
//改
//使用"周芷若"来替换[9,11)范围内的字符:
s.replace(9,11,"周芷若");
System.out.println(s); //"hello,张三丰周芷若true10.5"
//查
//查找指定的字符串第一次出现的索引,如果找不到就返回-1
int index=s.indexOf("张三丰");
System.out.println(index); //6
//插
//在索引为9的位置插入"赵敏",原来索引为9的内容自动后移
s.insert(9,"赵敏");
System.out.println(s); //"hello,张三丰赵敏周芷若true10.5"
//长度
System.out.println(s.length()); //22
}
四.代码分析------StringBuffer类的练习:
public static void main(String[] args) {
//多说一句:空指针异常发生情况:
//String s=null; //这种不会发生异常
//System.out.println(s); //会正常输出null
//但是如果输出长度就会发生空指针异常,因为空的字符串长度为0
//System.out.println(s.length());
String str=null;
StringBuffer sb=new StringBuffer();
sb.append(str); //在sb对象内容后面追加了str,但是str是空的
//不会报错,因为这里调用了appendNull()方法,如果追加的是空字符串,则把null拆成字符追加到value数组中
System.out.println(sb.length()); //不会报错, 'n','u','l','l',是长度为4
System.out.println(sb); //输出null
//这个会抛出空指针异常
//因为StringBuffer的构造器是super(str.length()+16)创建的,使用str,length()就会有空指针异常
StringBuffer sb1=new StringBuffer(str); //这句会报错
}
五. StringBuilder类 :
StringBuilder类和StringBuffer类的方法都是一样的 , 也是继承了AbstractStringBuilder类且实现了Serializable类 , 都是可以串行化的( 也就是可以在网络上传输 ) ; 但是StringBuilder类用于单线程 , 而StringBuffer类用于多线程,所以StringBuilder类更快.
六.String类和StringBuffer类和StringBuilder类的区别:
1. String类:不可变字符序列,创建的字符串常量在常量池中,效率低,但是复用率高(就是在常量池中的一个字符串,在堆中的对象都可以指向它);
2. StringBuffer类:可变字符序列,创建的字符串在堆中,效率较高,线程安全(多线程);
3. StringBuilder类:可变字符序列,创建的字符串在堆中,效率最高,线程不安全(单线程);
结论: 如果对String类做大量修改,不要使用String类,因为它是不可变字符序列 (final value[]);