StringBuffer 和 StringBuilder

对字符串进行修改时,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类的不同:

  • String 是被 final 修饰的,他的长度不可变(即使调用 String 的 concat 方法,那也是把字符串拼接起来并重新创建一个对象,把拼接后的 String 的值赋给新创建的对象)。
  • StringBuffer 和 StringBuilder 类的对象,长度可变,能够被多次的修改,并且不产生新的未使用对象
  • 相比较于 StringBuffer,String 一旦发生长度变化,是非常耗费内存的!

StringBuffer 和 StringBuilder

使用 StringBuffer 类时:

  • 每次都会对 StringBuffer 对象本身进行操作。
  • 不生成新的对象。
  • 如果需要对字符串进行修改,推荐使用 StringBuffer。

StringBuilder 和StringBuffer 不同:

Java String、StringBuffer 和 StringBuilder 的区别 | 菜鸟教程 (runoob.com)

  • StringBuilder 线程不安全(不能同步访问),运行效率快
  • StringBuffer 线程安全运行效率慢
  • 速度快,多数情况下建议使用 StringBuilder 类。
  • 在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

示例:

public class Test{
    public static void main(String args[]){
        StringBuilder sb = new StringBuilder(10);
        sb.append("xxxxxb..");
        System.out.println(sb);  
        sb.append("!");
        System.out.println(sb); 
        sb.insert(8, "Java");
        System.out.println(sb); 
        sb.delete(5,8);
        System.out.println(sb);  
    }
}

/*编译运行结果:
xxxxxb..
xxxxxb..!
xxxxxb..Java!
xxxxxJava!
*/

public class Test2{
  public static void main(String args[]){
    StringBuffer sBuffer = new StringBuffer("哈哈哈哈哈:");
    sBuffer.append("1");
    sBuffer.append(".2");
    sBuffer.append(".3");
    System.out.println(sBuffer);  
  }
}

/*编译运行结果:
哈哈哈哈哈:1.2.3
*/

StringBuffer 方法

以下是 StringBuffer 类支持的主要方法:

序号 方法描述
1 public StringBuffer append(String s) 将指定的字符串追加到此字符序列。
2 public StringBuffer reverse() 将此字符序列用其反转形式取代。
3 public delete(int start, int end) 移除此序列的子字符串中的字符。
4 public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。
5 insert(int offset, String str) 将 str 参数的字符串插入此序列中。
6 replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。

更多内容:

  • StringBuffer 类:https://www.runoob.com/manual/jdk11api/java.base/java/lang/StringBuffer.html
  • StringBuilder 类:https://www.runoob.com/manual/jdk11api/java.base/java/lang/StringBuilder.html

**JAVA 中的 StringBuilder 和 StringBuffer 适用的场景是什么? **

最简单的回答是,stringbuffer 基本没有适用场景,你应该在所有的情况下选择使用 stringbuiler,除非你真的遇到了一个需要线程安全的场景。

关于线程安全,即使你真的遇到了这样的场景,很不幸的是,恐怕你仍然有 99.99…99% 的情况下没有必要选择 stringbuffer,因为 stringbuffer 的线程安全,仅仅是保证 jvm 不抛出异常顺利的往下执行而已,它可不保证逻辑正确和调用顺序正确。大多数时候,我们需要的不仅仅是线程安全,而是锁。

最后,为什么会有 stringbuffer 的存在,如果真的没有价值,为什么 jdk 会提供这个类?答案太简单了,因为最早是没有 stringbuilder 的,sun 的人不知处于何种愚蠢的考虑,决定让 stringbuffer 是线程安全的,然后大约 10 年之后,人们终于意识到这是一个多么愚蠢的决定,意识到在这 10 年之中这个愚蠢的决定为 java 运行速度慢这样的流言贡献了多大的力量,于是,在 jdk1.5 的时候,终于决定提供一个非线程安全的 stringbuffer 实现,并命名为 stringbuilder。顺便,javac 好像大概也是从这个版本开始,把所有用加号连接的 string 运算都隐式的改写成 stringbuilder,从 jdk1.5 开始,严格地说,如果没有循环的情况下,单行用加号拼接字符串是没有性能损失的,java 编译器会隐式的替换成 stringbuilder,但在有循环的情况下,编译器没法做到足够智能的替换,仍然会有不必要的性能损耗,因此,用循环拼接字符串的时候,还是老老实实的用 stringbuilder 吧。

上一篇:利用注解 + 反射消除重复代码,妙!


下一篇:Java语法08-API