Java Notes
Complete guide to StringBuffer in Java covering thread-safe mutable strings, methods, internal working, capacity management, performance comparison with String and StringBuilder.
What is StringBuffer?
StringBuffer is a mutable, thread-safe class for handling character sequences. Unlike String (which creates a new object for every modification), StringBuffer modifies its internal character array in-place, making it much more efficient for repeated string modifications.
Key Characteristics
| Feature | StringBuffer |
|---|---|
| Mutability | Mutable — content can be changed |
| Thread Safety | Thread-safe — all methods are synchronized |
| Performance | Slower than StringBuilder (due to synchronization overhead) |
| Package | java.lang (auto-imported) |
| Implements | CharSequence, Appendable, Serializable |
| Default Capacity | 16 characters |
| Final class? | No (can be subclassed, though rarely done) |
When to Use StringBuffer
Use StringBuffer when you need:
- Mutable string operations (append, insert, delete, reverse)
- Thread safety — multiple threads accessing the same buffer
- Better performance than String for repeated modifications
StringBuffer vs String — Memory Comparison
public class StringVsStringBuffer {
public static void main(String[] args) {
// String: creates new object each time
String s = "Hello";
System.out.println("String identity: " + System.identityHashCode(s));
s = s + " World"; // NEW object created!
System.out.println("After concat identity: " + System.identityHashCode(s));
System.out.println("Value: " + s);
System.out.println();
// StringBuffer: modifies same object
StringBuffer sb = new StringBuffer("Hello");
System.out.println("StringBuffer identity: " + System.identityHashCode(sb));
sb.append(" World"); // SAME object modified!
System.out.println("After append identity: " + System.identityHashCode(sb));
System.out.println("Value: " + sb);
}
}String identity: 1283928880 After concat identity: 295530567 Value: Hello World StringBuffer identity: 738847520 After append identity: 738847520 Value: Hello World
Key Difference: String creates a new object (different identity). StringBuffer modifies the same object (same identity).
Constructors
public class StringBufferConstructors {
public static void main(String[] args) {
// 1. Default constructor: empty buffer with capacity 16
StringBuffer sb1 = new StringBuffer();
System.out.println("Default: \"" + sb1 + "\" capacity=" + sb1.capacity() + " length=" + sb1.length());
// 2. With initial capacity
StringBuffer sb2 = new StringBuffer(50);
System.out.println("Capacity(50): \"" + sb2 + "\" capacity=" + sb2.capacity() + " length=" + sb2.length());
// 3. With initial string (capacity = string.length() + 16)
StringBuffer sb3 = new StringBuffer("Hello");
System.out.println("String(\"Hello\"): \"" + sb3 + "\" capacity=" + sb3.capacity() + " length=" + sb3.length());
// 4. With CharSequence
StringBuffer sb4 = new StringBuffer((CharSequence)"Java");
System.out.println("CharSequence: \"" + sb4 + "\" capacity=" + sb4.capacity() + " length=" + sb4.length());
}
}Default: "" capacity=16 length=0
Capacity(50): "" capacity=50 length=0
String("Hello"): "Hello" capacity=21 length=5
CharSequence: "Java" capacity=20 length=4Capacity formula: When created with a String, capacity = string.length() + 16.
Internal Working — Capacity Management
StringBuffer internally uses a resizable character array (byte array in Java 9+). When the array is full, it grows automatically.
Growth Strategy
When content exceeds capacity:
If still insufficient, new capacity = required length.
public class CapacityGrowth {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer(); // Capacity: 16
System.out.println("Initial capacity: " + sb.capacity());
sb.append("1234567890123456"); // Exactly 16 chars — fills capacity
System.out.println("After 16 chars - capacity: " + sb.capacity());
sb.append("7"); // 17th char — exceeds capacity, triggers growth
System.out.println("After 17 chars - capacity: " + sb.capacity());
// New capacity = (16 * 2) + 2 = 34
sb.append("12345678901234567"); // Now 34 chars — fills new capacity
System.out.println("After 34 chars - capacity: " + sb.capacity());
sb.append("1"); // 35th char — exceeds again
System.out.println("After 35 chars - capacity: " + sb.capacity());
// New capacity = (34 * 2) + 2 = 70
}
}Initial capacity: 16 After 16 chars - capacity: 16 After 17 chars - capacity: 34 After 34 chars - capacity: 34 After 35 chars - capacity: 70
Memory Diagram
| | - value | [H][i][ ][ ][ ]...[ ] (18 slots)| |
| | - count | 2 (actual characters) | |
| | - capacity | 18 (total slots available) | |
| | - value | [H][i][ ][W][o][r][l][d][ ]...| |
| | - count | 8 | |
| | - capacity | 18 (unchanged, still fits) | |
StringBuffer Methods
append() — Add to End
The most commonly used method. Has overloaded versions for all data types.
public class AppendDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // String
sb.append(2024); // int
sb.append(' '); // char
sb.append(3.14); // double
sb.append(true); // boolean
sb.append(new char[]{'!','!'}); // char array
System.out.println(sb.toString());
// Method chaining (append returns the same StringBuffer)
StringBuffer sb2 = new StringBuffer();
sb2.append("Name: ").append("Alice").append(", Age: ").append(25);
System.out.println(sb2);
}
}Hello World2024 3.14true!! Name: Alice, Age: 25
insert() — Add at Position
public class InsertDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello World");
System.out.println("Original: " + sb);
sb.insert(5, " Beautiful");
System.out.println("After insert at 5: " + sb);
sb.insert(0, ">>> ");
System.out.println("After insert at 0: " + sb);
sb.insert(sb.length(), " <<<");
System.out.println("After insert at end: " + sb);
}
}Original: Hello World After insert at 5: Hello Beautiful World After insert at 0: >>> Hello Beautiful World After insert at end: >>> Hello Beautiful World <<<
delete() and deleteCharAt()
public class DeleteDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello Beautiful World");
System.out.println("Original: " + sb);
// delete(start, end) — end is exclusive
sb.delete(5, 15); // Removes " Beautiful"
System.out.println("After delete(5,15): " + sb);
// deleteCharAt(index)
sb.deleteCharAt(0); // Removes 'H'
System.out.println("After deleteCharAt(0): " + sb);
}
}Original: Hello Beautiful World After delete(5,15): Hello World After deleteCharAt(0): ello World
replace() — Replace Range
public class ReplaceDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello World");
System.out.println("Original: " + sb);
// replace(start, end, newString)
sb.replace(6, 11, "Java");
System.out.println("After replace: " + sb);
// Replacement can be different length
sb.replace(0, 5, "Hi");
System.out.println("After shorter replace: " + sb);
}
}Original: Hello World After replace: Hello Java After shorter replace: Hi Java
reverse()
public class ReverseDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello World");
System.out.println("Original: " + sb);
sb.reverse();
System.out.println("Reversed: " + sb);
// Palindrome check using StringBuffer
String word = "madam";
String reversed = new StringBuffer(word).reverse().toString();
System.out.println("\n\"" + word + "\" is palindrome: " + word.equals(reversed));
}
}Original: Hello World Reversed: dlroW olleH "madam" is palindrome: true
Other Useful Methods
public class OtherMethods {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello World");
// charAt and setCharAt
System.out.println("charAt(0): " + sb.charAt(0));
sb.setCharAt(0, 'h');
System.out.println("After setCharAt(0, 'h'): " + sb);
// substring
System.out.println("substring(6): " + sb.substring(6));
System.out.println("substring(0,5): " + sb.substring(0, 5));
// indexOf and lastIndexOf
sb = new StringBuffer("Java is great. Java is fun.");
System.out.println("indexOf(\"Java\"): " + sb.indexOf("Java"));
System.out.println("lastIndexOf(\"Java\"): " + sb.lastIndexOf("Java"));
// length and capacity
System.out.println("length: " + sb.length());
System.out.println("capacity: " + sb.capacity());
// ensureCapacity
sb.ensureCapacity(100);
System.out.println("After ensureCapacity(100): " + sb.capacity());
// trimToSize — reduces capacity to match length
sb.trimToSize();
System.out.println("After trimToSize: " + sb.capacity());
}
}charAt(0): H
After setCharAt(0, 'h'): hello World
substring(6): World
substring(0,5): hello
indexOf("Java"): 0
lastIndexOf("Java"): 15
length: 27
capacity: 43
After ensureCapacity(100): 100
After trimToSize: 27Thread Safety Demonstration
StringBuffer is synchronized — only one thread can execute a method at a time:
Final length: 2000 Expected: 2000 Thread-safe? true
With StringBuffer: Length is always exactly 2000 (thread-safe). With StringBuilder (not synchronized): Length might be less than 2000 (race condition).
StringBuffer vs StringBuilder vs String
| Feature | String | StringBuffer | StringBuilder |
|---|---|---|---|
| Mutability | Immutable | Mutable | Mutable |
| Thread Safety | Yes (immutable) | Yes (synchronized) | No |
| Performance | Slowest for modifications | Medium | Fastest for modifications |
| Since | JDK 1.0 | JDK 1.0 | JDK 1.5 |
| Use Case | Constants, keys | Multi-threaded modification | Single-threaded modification |
Performance Comparison
String: 3850 ms StringBuffer: 5 ms StringBuilder: 3 ms
Converting StringBuffer
To String: Hello World From String: Java Programming To char[]: [H, e, l, l, o, , W, o, r, l, d]
Common Mistakes
- Using StringBuffer when not needed — use StringBuilder for single-threaded code
- Comparing StringBuffer with == — use toString() first, then compare
- Not checking index bounds before insert/delete operations
- Forgetting that StringBuffer doesn't override equals() — uses Object.equals (reference comparison)
- Creating unnecessary StringBuffer for simple operations — "Hello" + name is fine for one concat
Best Practices
- Use StringBuilder unless thread safety is specifically required
- Set initial capacity if you know the approximate final size:
new StringBuffer(expectedSize) - Use method chaining for cleaner code:
sb.append("a").append("b").append("c") - Call trimToSize() after building if memory matters
- Convert to String only when finished building
- Prefer StringBuffer in servlet/multi-threaded environments
- Don't use for immutable needs — use String for constants and map keys
Interview Questions
Q1: What is StringBuffer? A mutable, thread-safe class for building and modifying character sequences. It modifies content in-place instead of creating new objects.
Q2: How is StringBuffer thread-safe? All public methods are declared synchronized, ensuring only one thread can execute any method at a time.
Q3: What is the default capacity? 16 characters. When created with a string, capacity = string.length() + 16.
Q4: How does capacity grow? New capacity = (old capacity × 2) + 2. If still insufficient, it grows to the required size.
Q5: StringBuffer vs StringBuilder? Both are mutable. StringBuffer is synchronized (thread-safe, slower). StringBuilder is non-synchronized (not thread-safe, faster).
Q6: Does StringBuffer override equals()? No. It uses Object.equals() which compares references. To compare content, convert to String first.
Q7: Can StringBuffer be used as HashMap key? Not recommended — it doesn't override hashCode/equals properly, and being mutable means the hash could change.
Q8: What is the return type of append()? Returns StringBuffer (the same object), enabling method chaining.
Q9: How to reverse a string using StringBuffer? new StringBuffer(str).reverse().toString()
Q10: What happens if you pass null to append()? It appends the literal string "null" (4 characters).
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for StringBuffer in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, fundamentals, strings, stringbuffer
Related Java Master Course Topics