In Java, the String class is one of the most frequently used and fundamental building blocks of application logic. A String represents an immutable sequence of characters and provides a rich API for manipulation, transformation, comparison, and formatting.
This tutorial explains Strings in depth from creation and immutability to performance considerations and best practices to help you write robust, efficient Java code.
What Is a Java String?
A String in Java is an object that encapsulates a sequence of characters. It is defined by the java.lang.String class, which is immutable — once created, its value cannot be changed.
This immutability enables:
- Security (no unexpected modifications)
- Safe caching in the String pool
- Efficient sharing across threads
Creating Java Strings
You can create strings in two ways:
String Literal
A string literal is created and stored in the String pool:
String s1 = "Hello";
String s2 = "Hello";
Both s1 and s2 refer to the same object in the String pool.
Using the String Constructor
String s3 = new String("Hello");
This creates a new object on the heap even if an equivalent literal exists.
String Immutability Explained
Once a String object is created, it cannot be modified. Any “modification” results in a new String object.
String s = "Hello";
s = s.concat(" World");
Here, "Hello" remains intact, and a new string "Hello World" is created. The original string stays unchanged.
String Pool and Memory Management
The String pool (internal memory for literals) improves performance and saves memory.
String a = "Tech";
String b = "Tech";
Both point to the same memory location. But:
String c = new String("Tech");
Creates a new object outside the pool.
Use intern() to move a heap object to the pool:
String d = new String("Tech").intern();
Now d references the pooled string.
Comparing Strings
Using ==
Checks reference equality, not content equality:
s1 == s2 // true for pooled literals
s1 == s3 // false for new String(...)
Using equals()
Compares actual content:
s1.equals(s3) // true
Using equalsIgnoreCase()
Ignores case differences:
"name".equalsIgnoreCase("NAME") // true
Common String Methods
Java’s String API is extensive. Here are frequently used methods:
Length and Char Access
int len = s.length();
char ch = s.charAt(2);
Substring Extraction
String sub = s.substring(0, 3);
Case Transformations
String upper = s.toUpperCase();
String lower = s.toLowerCase();
Searching and Matching
int index = s.indexOf("lo");
boolean found = s.contains("He");
Replacement
String replaced = s.replace("a", "b");
Splitting and Joining
Splitting
String[] parts = "a,b,c".split(",");
Joining
String joined = String.join("-", "a", "b", "c");
Formatting Strings
Use format() for structured output:
String msg = String.format("User %s has %d points", "Alice", 42);
This is cleaner than concatenation for complex output.
Immutable vs Mutable Alternatives
Since Strings are immutable, modifications can lead to excessive allocations in loops.
StringBuilder
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" World");
String result = sb.toString();
Use StringBuilder when building strings with many append operations.
Performance Considerations
Immutability ensures safety and pooling benefits, but inefficient use can impact performance:
- Avoid repeated concatenations inside loops using
+ - Prefer
StringBuilderfor dynamic text creation - Use
intern()only when needed (pool overhead)
Example of inefficient concatenation:
String result = "";
for (String s : list) {
result += s; // Creates multiple intermediate Strings
}
More efficient:
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append(s);
}
String result = sb.toString();
Converting Between String and Primitive Types
Primitives to String
String s = String.valueOf(123);
String to Primitives
int i = Integer.parseInt("42");
double d = Double.parseDouble("3.14");
Handle potential NumberFormatException.
Unicode and Encoding
Strings represent text as Unicode sequences. Be mindful when converting byte streams:
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
String restored = new String(bytes, StandardCharsets.UTF_8);
Always specify character sets to avoid platform default pitfalls.
Regular Expressions with String
Use matches() and replaceAll() for regex patterns:
boolean isMatch = "abc123".matches("\\w+");
String cleaned = s.replaceAll("[^0-9]", "");
Common String Mistakes
- Using
==for content comparison - Concatenating inside hot loops
- Ignoring null checks before calling methods
Always validate input and prefer safe comparison:
"constant".equals(variable);
Best Practices (Senior Engineering Insight)
- Prefer
StringBuilderfor dynamic text construction - Use String constants and pooling to reduce memory footprint
- Avoid null pointer by checking inputs before calling methods
- Leverage built-in methods instead of manual loops
These practices lead to robust, maintainable code.
Summary
Java Strings are fundamental and versatile. Understanding creation, immutability, comparison, transformations, and performance is essential for writing efficient Java applications. This guide covered creation patterns, comparisons, common methods, memory considerations, and best practices to help you master Java text handling.


