Java StringBuffer Class
Last modified: April 13, 2025
The java.lang.StringBuffer
class is a thread-safe, mutable sequence
of characters. Unlike String objects, StringBuffer can be modified after
creation. It provides various methods for string manipulation operations.
StringBuffer is similar to StringBuilder but with one key difference: all its methods are synchronized, making it thread-safe. This makes StringBuffer a good choice when working with strings in multi-threaded environments.
StringBuffer Class Methods
The StringBuffer class provides many methods for string manipulation. These include methods for appending, inserting, deleting, and reversing content. The class also provides capacity management methods.
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() {...} }
The code above shows the main methods provided by the StringBuffer class. These methods allow for flexible string manipulation while maintaining thread safety.
Creating StringBuffer Objects
StringBuffer objects can be created in several ways: with no initial content, with an initial string, or with a specified initial capacity. The capacity determines how much memory is initially allocated.
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); } }
This example demonstrates different ways to create StringBuffer objects. The default constructor creates an empty buffer with capacity 16. The String constructor creates a buffer with the string content and appropriate capacity.
append Method
The append
method adds content to the end of the StringBuffer. It
is overloaded to accept various data types including primitives, objects, and
character arrays. The method returns the same StringBuffer for method chaining.
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()); } }
This example shows how the append
method can handle different data
types. The StringBuffer automatically grows its capacity when needed. Method
chaining allows for concise code by returning the StringBuffer reference.
insert Method
The insert
method adds content at a specified position in the
StringBuffer. Like append, it supports various data types. The position must be
within the current bounds of the buffer.
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()); } } }
This example demonstrates the insert
method with different data
types. We show valid insert positions and what happens when attempting to insert
at an invalid position. Inserting at length() is equivalent to append.
delete and deleteCharAt Methods
The delete
method removes a sequence of characters between specified
indices. The deleteCharAt
method removes a single character at a
specified position. Both methods adjust the buffer contents accordingly.
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()); } } }
This example shows various deletion operations. The delete method removes characters between two indices (start inclusive, end exclusive). We demonstrate deleting ranges, single characters, and handling invalid indices.
reverse Method
The reverse
method reverses the sequence of characters in the
StringBuffer. This operation is performed in place, modifying the original
buffer. The method returns the StringBuffer reference for method chaining.
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, "---")); } }
This example demonstrates the reverse
method. We show simple
reversal, palindrome checking, and method chaining combining reverse with other
StringBuffer operations. The reversal affects the original buffer directly.
Capacity Management
StringBuffer manages memory using a capacity system. The capacity is the amount
of allocated memory, while length is the actual content size. Methods like
ensureCapacity
and setLength
help manage this.
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()); } }
This example demonstrates StringBuffer capacity management. The buffer
automatically grows when needed, but we can also pre-allocate space with
ensureCapacity
. setLength
can truncate or expand the
content, while trimToSize
reduces capacity to match length.
Thread Safety Demonstration
StringBuffer's thread safety makes it suitable for multi-threaded environments. Multiple threads can safely call StringBuffer methods without external synchronization. This example demonstrates this behavior.
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()); } }
This example demonstrates StringBuffer's thread safety. Multiple threads concurrently append to the same StringBuffer without data corruption. The synchronized methods ensure that all operations complete atomically. The final length confirms all additions were preserved.
Source
Java StringBuffer Class Documentation
In this article, we've covered all major aspects of the Java StringBuffer class with practical examples. StringBuffer provides thread-safe, mutable string operations essential for complex string manipulation in multi-threaded contexts.
Author
List all Java tutorials.