- StringBuffer
基本介绍:StringBuffer
是 Java 标准库中的一个类,用于处理可变的字符串序列。它与不可变的字符串 String
类似,但是 StringBuffer
允许对字符串内容进行修改和操作,适用于需要频繁拼接和修改字符串的情况,尤其在多线程环境下推荐使用线程安全版本的 StringBuilder
。
-
可变性:
StringBuffer
对象的内容可以被修改,包括添加、插入、删除和替换字符等操作。 -
线程安全性:
StringBuffer
是线程安全的,即多个线程同时对一个StringBuffer
进行操作时,不会出现数据不一致的问题。这是通过使用同步机制来实现的,但这也会带来一些性能开销。如果不需要线程安全,推荐使用性能更好的StringBuilder
。 -
构造方法:
StringBuffer
提供了多个构造方法,可以通过字符串、字符数组、初始容量等来初始化。 -
常用方法:
StringBuffer
提供了一系列的方法用于字符串操作,包括:append()
:将指定的数据添加到字符串序列的末尾。insert()
:在指定位置插入数据。delete()
:删除指定位置的字符。replace()
:替换指定范围内的字符。reverse()
:反转字符串序列。...
-
性能: 由于
StringBuffer
使用了同步机制以实现线程安全,因此在单线程环境中,性能可能比StringBuilder
差一些。如果不需要线程安全,并且在单线程环境下频繁修改字符串内容,推荐使用StringBuilder
。
StringBuffer VS String:
StringBuffer
和 String
是 Java 中用于处理字符串的两个不同的类,它们在可变性、线程安全性和性能方面有着明显的区别。
-
可变性:
String
:String
类是不可变的,意味着一旦创建了一个String
对象,其内容就不能被修改。任何对String
对象的修改都会创建一个新的String
对象。StringBuffer
:StringBuffer
类是可变的,允许对字符串内容进行修改、添加和删除等操作。
-
线程安全性:
String
:String
是线程安全的,因为它的内容一旦创建就不能被修改,不存在线程安全的问题。StringBuffer
:StringBuffer
是线程安全的,支持多线程环境下的并发操作。它使用同步机制来确保线程安全,但可能会有性能开销。
-
性能:
String
: 由于String
是不可变的,每次对字符串进行修改都会创建一个新的String
对象,这可能会导致大量的对象创建和内存消耗。当字符串很少修改,被多个对象引用时,使用String,比如配置信息等。StringBuffer
:StringBuffer
是可变的,对字符串的修改不会每次(这边是根据数组是否已满来考虑是否要创建新的对象的,可以看源码)创建新的对象,因此在频繁修改字符串的情况下,性能可能会更好。但是,由于线程安全的设计,它在单线程环境下的性能可能不如StringBuild
。
String、StringBuffer 和 StringBuilder 的选择:
- 当字符串很少修改,被多个对象引用时(复用率高),使用String,比如配置信息等。
- 如果需要频繁修改字符串内容,并且不需要考虑线程安全问题,应该使用
StringBuilder
,它是非线程安全但性能更好的可变字符串类。 - 如果在多线程环境下需要进行字符串操作,可以使用
StringBuffer
,以保证线程安全性。
String和 StringBuffer的相互转换:
String 转换为 StringBuffer:
- 使用
StringBuffer
构造函数:通过将一个String
对象传递给StringBuffer
的构造函数,可以创建一个包含相同内容的可变字符串。 - 使用
StringBuffer
的append
方法:你可以通过使用append
方法来将一个String
添加到一个现有的StringBuffer
中。
StringBuffer 转换为 String:
- 使用
StringBuffer
的toString
方法:StringBuffer
类提供了一个名为toString
的方法,可以将其内容转换为一个不可变的String
对象。 - 使用
String
构造函数:通过将一个StringBuffer
对象传递给String
的构造函数,可以创建一个包含相同内容的不可变字符串。
代码:
public class StringAndStringBuffer {
public static void main(String[] args) {
//String——>StringBuffer
String str = "ret1";
//方式 1 使用构造器
//注意: 返回的才是 StringBuffer 对象,对 str 本身没有影响
StringBuffer stringBuffer = new StringBuffer(str);
//方式 2 使用的是 append 方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str);
//StringBuffer ->String
StringBuffer stringBuffer3 = new StringBuffer("ret2");
//方式 1 使用 StringBuffer 提供的 toString 方法
String s = stringBuffer3.toString();
//方式 2: 使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}
StringBuffer的常见方法:
代码:
public class StringBufferMethods {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("ret");
//增
s.append(',');// "ret,"
s.append("ret");//"ret,ret"
s.append(" ret").append(123).append(true).append(99.9);//"ret,ret ret123true99.9"
//删
/*
* 删除索引为>=start && <end 处的字符
* 解读: 删除的字符 [3, 7)
*/
s.delete(3, 7);
System.out.println(s);//"ret ret123true99.9"
//改
//使用ter替换 索引 [0,3)的字符
s.replace(0, 3, "ter");
System.out.println(s);//"ter ret123true99.9"
//查找指定的子串在字符串第一次出现的索引,如果找不到返回-1
int indexOf = s.indexOf("ret");
System.out.println(indexOf);//4
//插
//在索引为 3 的位置插入 "ret",原来索引为 3 的内容自动后移
s.insert(3, " ret");
System.out.println(s);//"ter ret ret123true99.9"
//长度
System.out.println(s.length());//22
System.out.println(s);
}
}
一道有趣的题目,可以让你了解到相关源码
代码:
public class StringBufferAppend {
public static void main(String[] args) {
String str = null;// ok
StringBuffer sb = new StringBuffer(); //ok
sb.append(str);//需要看源码 , 底层调用的是 AbstractStringBuilder的appendNull
/*
源码:
* private 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;
* }
*/
System.out.println(sb.length());//4
System.out.println(sb);//null
//下面的构造器,会抛出 NullPointerException
StringBuffer sb1 = null;//看底层源码 super(str.length() + 16);
try {
sb1 = new StringBuffer(str);
/*
源码:
* public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
* */
} catch (Exception e) {
//e.printStackTrace();
System.out.println("异常信息是:"+e.getMessage());
}
System.out.println(sb1);
}
}
- StringBuild
基本介绍:StringBuilder
是 Java 中用于处理可变字符串的类,它与 StringBuffer
类似,但不提供同步机制,因此在单线程环境下性能更好
-
可变性:
StringBuilder
是可变的,这意味着你可以通过修改其内容来构建和修改字符串,而不需要创建新的对象。 -
性能:相对于
StringBuffer
,StringBuilder
没有同步机制,因此在单线程环境中的性能更高。如果你不需要考虑多线程问题,可以优先选择StringBuilder
。 -
方法:
StringBuilder
提供了一系列方法用于字符串的操作,包括插入、追加、替换、删除等操作。 -
线程安全性:与
StringBuffer
不同,StringBuilder
不是线程安全的。如果在多线程环境中使用StringBuilder
进行并发操作,可能会出现问题。如果你需要在多线程环境中使用可变字符串,应该选择StringBuffer
或使用适当的同步机制。 -
容量自动增长:
StringBuilder
会自动增加内部缓冲区的大小以适应字符串的增长。你可以使用capacity
和ensureCapacity
方法来管理容量。 -
链式调用:由于
StringBuilder
的方法返回其自身的引用,你可以进行链式调用,使代码更简洁。
方法和StringBuffer一样,就不再描述了