ZetCode

Java StringBuffer 类

最后修改时间:2025 年 4 月 13 日

java.lang.StringBuffer 类是一个线程安全、可变的字符序列。 与 String 对象不同,StringBuffer 在创建后可以被修改。 它提供了各种用于字符串操作的方法。

StringBuffer 与 StringBuilder 类似,但有一个关键区别:它的所有方法都是同步的,使其成为线程安全的。 这使得 StringBuffer 成为在多线程环境中处理字符串的理想选择。

StringBuffer 类方法

StringBuffer 类提供了许多用于字符串操作的方法。 这些方法包括用于追加、插入、删除和反转内容的方法。 该类还提供了容量管理方法。

public final class StringBuffer {
    public StringBuffer() {...}
    public StringBuffer(int capacity) {...}
    public StringBuffer(String str) {...}
    public synchronized StringBuffer append(...) {...}
    public synchronized StringBuffer insert(...) {...}
    public synchronized StringBuffer delete(...) {...}
    public synchronized StringBuffer reverse() {...}
    public synchronized int length() {...}
    public synchronized int capacity() {...}
    public synchronized void ensureCapacity(int minimum) {...}
    public synchronized char charAt(int index) {...}
    public synchronized void setCharAt(int index, char ch) {...}
    public synchronized String substring(...) {...}
    public synchronized String toString() {...}
}

上面的代码显示了 StringBuffer 类提供的主要方法。 这些方法允许灵活的字符串操作,同时保持线程安全。

创建 StringBuffer 对象

StringBuffer 对象可以通过多种方式创建:不带初始内容、带初始字符串或带指定的初始容量。 容量决定了最初分配的内存量。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        // Empty StringBuffer with default capacity (16)
        StringBuffer sb1 = new StringBuffer();
        System.out.println("sb1 capacity: " + sb1.capacity());
        
        // StringBuffer with initial string
        StringBuffer sb2 = new StringBuffer("Hello");
        System.out.println("sb2 content: " + sb2);
        System.out.println("sb2 capacity: " + sb2.capacity());
        
        // StringBuffer with specified capacity
        StringBuffer sb3 = new StringBuffer(50);
        System.out.println("sb3 capacity: " + sb3.capacity());
        
        // Adding content to empty buffer
        sb1.append("Java StringBuffer");
        System.out.println("sb1 content: " + sb1);
    }
}

此示例演示了创建 StringBuffer 对象的不同方法。 默认构造函数创建一个容量为 16 的空缓冲区。 String 构造函数创建一个具有字符串内容和适当容量的缓冲区。

append 方法

append 方法将内容添加到 StringBuffer 的末尾。 它被重载以接受各种数据类型,包括基本类型、对象和字符数组。 该方法返回相同的 StringBuffer,用于方法链式调用。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        
        // Appending different types
        sb.append("String: ");
        sb.append(100);       // int
        sb.append(' ');       // char
        sb.append(true);      // boolean
        sb.append(3.14);      // double
        sb.append(new char[]{'a', 'b', 'c'}); // char array
        
        System.out.println("After append: " + sb);
        
        // Method chaining
        sb.append(" more ").append("text");
        System.out.println("After chaining: " + sb);
        
        // Capacity grows automatically
        System.out.println("Final capacity: " + sb.capacity());
    }
}

此示例显示了 append 方法如何处理不同的数据类型。 StringBuffer 会在需要时自动增加其容量。 方法链式调用通过返回 StringBuffer 引用来实现简洁的代码。

insert 方法

insert 方法在 StringBuffer 中的指定位置添加内容。 与 append 类似,它支持各种数据类型。 该位置必须在缓冲区的当前边界内。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Java is great");
        
        // Insert at position 4
        sb.insert(4, " programming");
        System.out.println("After first insert: " + sb);
        
        // Insert different types
        sb.insert(0, 2023);   // int
        sb.insert(4, ' ');    // char
        sb.insert(5, true);   // boolean
        
        System.out.println("After multiple inserts: " + sb);
        
        // Insert at the end (same as append)
        sb.insert(sb.length(), " language");
        System.out.println("Final result: " + sb);
        
        // Invalid position throws exception
        try {
            sb.insert(100, "error");
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("Caught exception: " + e.getMessage());
        }
    }
}

此示例演示了具有不同数据类型的 insert 方法。 我们展示了有效的插入位置以及尝试在无效位置插入时会发生什么。 在 length() 处插入等同于 append。

delete 和 deleteCharAt 方法

delete 方法删除指定索引之间的字符序列。 deleteCharAt 方法删除指定位置的单个字符。 这两种方法都会相应地调整缓冲区内容。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Java StringBuffer Example");
        
        // Delete range (start inclusive, end exclusive)
        sb.delete(5, 17);
        System.out.println("After delete: " + sb);
        
        // Delete single character
        sb.deleteCharAt(5);
        System.out.println("After deleteCharAt: " + sb);
        
        // Delete from start
        sb.delete(0, 4);
        System.out.println("After deleting first word: " + sb);
        
        // Delete to end
        sb.delete(5, sb.length());
        System.out.println("After deleting suffix: " + sb);
        
        // Invalid indices throw exception
        try {
            sb.delete(10, 5);
        } catch (StringIndexOutOfBoundsException e) {
            System.out.println("Caught exception: " + e.getMessage());
        }
    }
}

此示例显示了各种删除操作。 delete 方法删除两个索引之间的字符(包括起始索引,不包括结束索引)。 我们演示了删除范围、单个字符和处理无效索引。

reverse 方法

reverse 方法反转 StringBuffer 中字符的顺序。 此操作在原地执行,修改原始缓冲区。 该方法返回 StringBuffer 引用,用于方法链式调用。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello World");
        
        System.out.println("Original: " + sb);
        
        // Reverse the content
        sb.reverse();
        System.out.println("Reversed: " + sb);
        
        // Reverse back to original
        sb.reverse();
        System.out.println("Reversed again: " + sb);
        
        // Palindrome check
        StringBuffer palindrome = new StringBuffer("madam");
        System.out.println(palindrome + " is palindrome: " + 
            palindrome.toString().equals(palindrome.reverse().toString()));
        
        // Method chaining
        System.out.println(new StringBuffer("abc")
            .append("def")
            .reverse()
            .insert(3, "---"));
    }
}

此示例演示了 reverse 方法。 我们展示了简单的反转、回文检查以及将 reverse 与其他 StringBuffer 操作结合使用的方法链式调用。 反转直接影响原始缓冲区。

容量管理

StringBuffer 使用容量系统管理内存。 容量是分配的内存量,而长度是实际内容大小。 ensureCapacitysetLength 等方法有助于管理这一点。

Main.java
package com.zetcode;

public class Main {

    public static void main(String[] args) {
        // Default capacity is 16
        StringBuffer sb = new StringBuffer();
        System.out.println("Initial capacity: " + sb.capacity());
        System.out.println("Initial length: " + sb.length());
        
        // Adding content grows capacity as needed
        sb.append("This is a long string that exceeds default capacity");
        System.out.println("After append - capacity: " + sb.capacity());
        System.out.println("After append - length: " + sb.length());
        
        // Ensure minimum capacity
        sb.ensureCapacity(100);
        System.out.println("After ensureCapacity(100): " + sb.capacity());
        
        // Set explicit length
        sb.setLength(10);
        System.out.println("After setLength(10): " + sb);
        System.out.println("New length: " + sb.length());
        
        // Trim to size
        sb.trimToSize();
        System.out.println("After trimToSize - capacity: " + sb.capacity());
    }
}

此示例演示了 StringBuffer 容量管理。 缓冲区会在需要时自动增长,但我们也可以使用 ensureCapacity 预先分配空间。 setLength 可以截断或扩展内容,而 trimToSize 减小容量以匹配长度。

线程安全演示

StringBuffer 的线程安全性使其适用于多线程环境。 多个线程可以安全地调用 StringBuffer 方法,而无需外部同步。 此示例演示了此行为。

Main.java
package com.zetcode;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        final StringBuffer sharedBuffer = new StringBuffer();
        
        // Create multiple threads that append to the same buffer
        Thread[] threads = new Thread[5];
        for (int i = 0; i < threads.length; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    sharedBuffer.append("Thread " + threadId + ": " + j + "\n");
                    try {
                        Thread.sleep(10); // Simulate work
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            });
        }
        
        // Start all threads
        for (Thread t : threads) {
            t.start();
        }
        
        // Wait for all threads to complete
        for (Thread t : threads) {
            t.join();
        }
        
        // Verify all additions were made safely
        System.out.println("Final buffer content:");
        System.out.println(sharedBuffer);
        System.out.println("Total length: " + sharedBuffer.length());
    }
}

此示例演示了 StringBuffer 的线程安全性。 多个线程并发地追加到同一个 StringBuffer,而不会发生数据损坏。 同步方法确保所有操作都以原子方式完成。 最终长度确认所有添加都已保留。

来源

Java StringBuffer 类文档

在本文中,我们通过实际示例介绍了 Java StringBuffer 类的所有主要方面。 StringBuffer 提供了线程安全、可变的字符串操作,这对于多线程环境中复杂的字符串操作至关重要。

作者

我叫 Jan Bodnar,是一位敬业的程序员,在该领域拥有多年的经验。 我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。 凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程