The String class in Java is one of the most commonly used classes in the Java standard library. It represents a sequence of characters and provides various methods for string manipulation. Strings in Java are immutable, meaning their content cannot be changed after they are created. This immutability makes String objects thread-safe and efficient in certain contexts.
Key Features of the String Class
- Immutable: Once a String object is created, its value cannot be modified. Any operation that alters a string will create a new String object.
- Final Class: The String class is declared final, so it cannot be subclassed.
- Stored in the String Pool: Java uses a special memory region called the String Pool to store string literals. This optimizes memory usage and allows reusability.
- Implements Serializable and Comparable: Strings can be serialized, and they implement the Comparable interface for lexicographical comparison.
Creating Strings
There are two main ways to create a String:
Using String Literals:
String str1 = “Hello”;
- String literals are automatically added to the string pool.
Using the new Keyword:
String str2 = new String(“Hello”);
- This creates a new String object in the heap, even if an identical string exists in the pool.
Important String Methods
The String class provides numerous methods for working with strings. Below are some of the most commonly used methods:
Method | Description |
length() | Returns the length of the string. |
charAt(int index) | Returns the character at the specified index. |
substring(int start, int end) | Returns a substring from the specified start (inclusive) to end (exclusive). |
concat(String str) | Concatenates the specified string to the end of the current string. |
equals(Object obj) | Compares the current string with the specified object for equality. |
equalsIgnoreCase(String str) | Compares two strings, ignoring case differences. |
compareTo(String str) | Compares two strings lexicographically. |
toLowerCase() | Converts all characters in the string to lowercase. |
toUpperCase() | Converts all characters in the string to uppercase. |
trim() | Removes leading and trailing whitespace from the string. |
replace(char oldChar, char newChar) | Replaces all occurrences of oldChar with newChar. |
split(String regex) | Splits the string into an array of substrings based on the specified regular expression. |
contains(CharSequence s) | Checks if the string contains the specified sequence of characters. |
startsWith(String prefix) | Checks if the string starts with the specified prefix. |
endsWith(String suffix) | Checks if the string ends with the specified suffix. |
isEmpty() | Returns true if the string is empty (length is 0). |
String Immutability
The immutability of strings has several advantages:
- Thread Safety: Since strings cannot be modified, they can be shared between threads without additional synchronization.
- Hash Code Consistency: The hash code of a string is computed once and does not change, making strings ideal for use as keys in hash-based collections like HashMap.
However, immutability can also lead to higher memory usage when performing frequent string modifications, as each modification creates a new String object. For such scenarios, StringBuilder or StringBuffer should be used.
String Pool
The string pool is a special memory area where Java stores string literals. If two string literals have the same value, they will refer to the same object in the pool.
Example:
String str1 = “Hello”;
String str2 = “Hello”;
System.out.println(str1 == str2); // true (both refer to the same object in the pool)
However, using the new keyword bypasses the string pool:
String str3 = new String(“Hello”);
System.out.println(str1 == str3); // false (different objects)
Performance: String vs StringBuilder vs StringBuffer
- String: Immutable, creates new objects for every modification, less efficient for frequent changes.
- StringBuilder: Mutable, faster for single-threaded scenarios.
- StringBuffer: Mutable and thread-safe (synchronized), but slower than StringBuilder.
Example:
StringBuilder sb = new StringBuilder(“Hello”);
sb.append(” World”);
System.out.println(sb.toString()); // Hello World
Common Use Cases
- Data Parsing and Formatting: Splitting or concatenating strings.
- File Paths: Constructing or validating file paths.
- User Input Handling: Processing strings from user inputs.
- Regular Expressions: Pattern matching and extraction.
Example Code
public class StringExample {
public static void main(String[] args) {
String str1 = “Java”;
String str2 = “Programming”;
// String concatenation
String result = str1 + ” ” + str2;
System.out.println(“Concatenated String: ” + result);
// Using methods
System.out.println(“Length: ” + result.length());
System.out.println(“Substring: ” + result.substring(0, 4));
System.out.println(“Uppercase: ” + result.toUpperCase());
// Comparing strings
System.out.println(“Equals: ” + str1.equals(“java”)); // false
System.out.println(“Ignore Case Equals: ” + str1.equalsIgnoreCase(“java”)); // true
}
}
Output:
Concatenated String: Java Programming
Length: 16
Substring: Java
Uppercase: JAVA PROGRAMMING
Equals: false
Ignore Case Equals: true
The String class is versatile and essential for Java developers, providing powerful methods for handling and manipulating text.