Navigation
Java Full Course: Mastering the Language Strings in Java
Strings in Java
(Complete Notes | Beginner to Advanced | Professional & Exam-Oriented | Masterclass)
1. Introduction to Strings
In Java, a String is a sequence of characters used to represent text. Unlike many other programming languages where strings are arrays of characters, Java treats strings as objects of the built-in String class. Strings are immutable—once created, their values cannot be changed. This immutability enables features like string pooling, where literal strings are stored in a special heap area (the String Pool) to improve memory efficiency and performance.
Java provides three main types for working with sequences of characters:
- String – immutable, thread safe, and the most commonly used.
- StringBuilder – mutable, not thread safe; best for single threaded string manipulation.
- StringBuffer – mutable, thread safe (synchronized); suitable for multi threaded environments.
In the following sections, we will explore:
- Creating and initializing strings
- String immutability and the String Pool
- Common String methods (length, charAt, substring, equals, etc.)
- String comparison (
==vsequals()) - Using StringBuilder and StringBuffer
- Performance considerations and best practices
2. What is a String?
A String in Java is a sequence of characters. It is a class (java.lang.String) and represents an immutable object. Once a String object is created, its value cannot be changed. Any operation that appears to modify a string actually creates a new String object.
3. Creating Strings
There are two primary ways to create a String:
a) Using String Literal
- This syntax creates a string literal. The JVM maintains a String Pool (also called String Intern Pool) to store such literals. If a literal already exists in the pool, a new object is not created; the existing reference is reused.
- This is memory efficient and the recommended way.
b) Using the new Keyword
- This creates a new
Stringobject on the heap, even if the same value exists in the String Pool. It forces creation of a new object.
Comparison:
4. String Immutability and the String Pool
Immutability means that once a String object is created, its content cannot be changed. Any method that seems to modify the string (e.g., toUpperCase(), concat(), replace()) returns a new String object.
Why immutability?
- Security: Strings are used in class loading, file paths, etc. Immutability prevents accidental or malicious changes.
- Thread safety: Immutable objects can be shared freely without synchronization.
- String Pool: Because strings are immutable, the JVM can safely store literals in a pool and reuse them, saving memory.
Example demonstrating immutability:
String Pool Internals:
- When a string literal is created, the JVM checks if an identical string already exists in the pool. If yes, the reference is reused; otherwise, a new string is added to the pool.
- You can manually add a string to the pool using
intern():
5. Common String Methods
The String class provides a rich set of methods. Here are the most frequently used ones:
| Method | Description | Example |
|---|---|---|
length() | Returns the number of characters. | "Java".length() → 4 |
charAt(int index) | Returns the character at the specified index. | "Java".charAt(1) → 'a' |
substring(int beginIndex, int endIndex) | Returns a substring (endIndex exclusive). | "Hello".substring(1,4) → "ell" |
toLowerCase() / toUpperCase() | Returns a new string in lower/upper case. | "Java".toUpperCase() → "JAVA" |
trim() | Removes leading and trailing whitespace. | " Hi ".trim() → "Hi" |
replace(char old, char new) | Replaces all occurrences of a character. | "Hello".replace('l','p') → "Heppo" |
startsWith(String prefix) / endsWith(String suffix) | Checks prefix or suffix. | "Hello".startsWith("He") → true |
contains(CharSequence s) | Checks if the string contains a sequence. | "Hello".contains("ell") → true |
indexOf(String str) | Returns the index of the first occurrence. | "Hello".indexOf("l") → 2 |
lastIndexOf(String str) | Returns the index of the last occurrence. | "Hello".lastIndexOf("l") → 3 |
equals(Object obj) | Compares content (case sensitive). | "Hi".equals("hi") → false |
equalsIgnoreCase(String another) | Compares content ignoring case. | "Hi".equalsIgnoreCase("hi") → true |
compareTo(String another) | Lexicographic comparison (returns int). | "a".compareTo("b") → negative |
split(String regex) | Splits the string into an array. | "a,b,c".split(",") → ["a","b","c"] |
join(CharSequence delimiter, CharSequence... elements) | Joins strings with a delimiter (static). | String.join("-", "a","b","c") → "a-b-c" |
isEmpty() | Returns true if length is 0. | "".isEmpty() → true |
isBlank() (Java 11+) | Returns true if string is empty or contains only whitespace. | " ".isBlank() → true |
Example usage:
6. String Comparison
[!IMPORTANT]
Use equals() to compare content, not ==.
==compares references (whether they point to the same object).equals()compares the character sequence.
Case insensitive comparison:
Lexicographic comparison:
7. String Concatenation
Concatenation can be done in several ways:
a) Using + Operator
- The compiler often uses
StringBuilderbehind the scenes.
b) Using concat() Method
c) Using StringBuilder or StringBuffer (efficient for many operations)
[!TIP]
Performance note: For multiple concatenations in a loop, use StringBuilder (or StringBuffer for thread safety) to avoid creating many intermediate String objects.
8. StringBuilder and StringBuffer
Both classes are mutable sequences of characters. They are used when you need to modify strings frequently.
| Feature | StringBuilder | StringBuffer |
|---|---|---|
| Mutability | Mutable | Mutable |
| Thread safety | Not synchronized (not thread safe) | Synchronized (thread safe) |
| Performance | Faster in single threaded environments | Slower due to synchronization overhead |
| Common methods | append(), insert(), delete(), reverse(), toString() | Same as StringBuilder |
Example:
When to use which:
- Use String for immutable text.
- Use StringBuilder for single threaded mutable text.
- Use StringBuffer when multiple threads may access the same buffer.
9. Escape Sequences and Unicode
Java strings support escape sequences for special characters:
| Escape | Meaning |
|---|---|
| ` | |
| ` | Newline |
\t | Tab |
\\\\ | Backslash |
\" | Double quote |
\' | Single quote |
\uXXXX | Unicode character (e.g., \u00A9 for ©) |
Example:
10. Converting Other Types to String
- Use
String.valueOf()for any primitive or object:
- Or use concatenation with an empty string:
- For objects,
toString()is called automatically.
11. Common Pitfalls and Best Practices
| Pitfall | Explanation / Solution |
|---|---|
| Using == for content comparison | Always use equals() for content. |
| Inefficient concatenation in loops | Use StringBuilder instead of + in loops. |
| Assuming strings are mutable | Remember immutability; each "modification" creates a new string. |
| Null strings | Calling methods on a null reference throws NullPointerException. Check with Objects.toString() or guard clauses. |
| String pool confusion | Use intern() only when necessary; premature use can lead to memory issues. |
| Not specifying charset when converting bytes | Always specify charset to avoid platform dependent results: new String(bytes, StandardCharsets.UTF_8). |
Best Practices:
- Use string literals when possible to benefit from the String Pool.
- For string concatenation in loops, prefer
StringBuilder. - Use
String.join()orString.format()for readable concatenation. - Use
isEmpty()orisBlank()(Java 11+) to check for empty or blank strings. - When comparing strings, handle null appropriately, e.g.,
Objects.equals(str1, str2).
12. Key Points to Remember
- Strings are objects of the
Stringclass and are immutable. - String literals are stored in the String Pool; duplicate literals share the same reference.
- Use
equals()for content comparison;==compares references. StringBuilder(mutable, not thread safe) andStringBuffer(mutable, thread safe) are for efficient string manipulation.- Common methods:
length(),charAt(),substring(),indexOf(),split(),trim(),toUpperCase(),toLowerCase(). - Escape sequences (
,\t, etc.) allow special characters in strings. - Always consider immutability when designing classes; using
Stringas a key in maps is safe because its hash code is cached.
