Feature |
CharSequence |
String |
Type |
Interface |
Class |
Mutability |
Can be mutable or immutable |
Immutable |
Implementations |
String, StringBuilder, StringBuffer, CharBuffer |
Directly instantiated |
Memory Efficiency |
Can be optimized using custom implementations |
Uses String pool |
Use Case |
Generic text handling |
Constant text values |
Strings in Character Arrays (char[])
Unlike String in Java, character arrays (char[]) can be changed by single characters. This is very useful for security-sensitive programs like password handling.
Output:

Concept of Memory Allocation of Strings in Java

It is very important for you to understand the memory allocation of Java Strings in order to develop efficient programs. Since Strings are immutable, their storage and retrieval are optimized by Java through mechanisms like the String Pool and different regions of heap memory.
1. Where are Strings Stored in Java?
Generally, Java uses two main memory spaces to store String objects:
- String Pool (String Interning): It resides in Heap Memory
- Heap Memory: This memory typically stores Normal String Objects
- Stack Memory: This memory stores String references
2. How are Strings Allocated in Memory?
a) String Pool (Interned Strings)
The Java String Pool is a special area in the heap where string literals are typically stored in order to avoid memory loss.
How it works?
- Whenever you create any String with double quotes (” “), Java first checks if the value is already in the pool.
- If already discovered, the same reference is returned.
- Otherwise, a new object is instantiated and inserted into the pool.
Example: String Pool Behavior
Output:

Key Takeaways:
- “Java” is placed in the String Pool only once and shared for both s1 and s2.
- s3 here is built using new, so it does not utilize the pool and gets a new memory allocation.
b) Heap Memory (Outside String Pool)
If a String is being created by invoking new String(“value”), it is stored outside the String Pool, straight into the Heap Memory.
Why use new String()?
- It simply disallows string interning in case we need a distinct instance.
- It is very Helpful in situations that need unique string objects, such as cryptographic applications.
String s1 = new String("Hello"); // Stored in Heap
String s2 = "Hello"; // Stored in the String Pool
System.out.println(s1 == s2); // false (Different memory locations)
Best Practice: Avoid new String(“value”) unless you need to save memory.
c) Stack Memory (Stores References to Strings)
Stack memory in Java cannot store string objects, but it stores references (pointers) to objects created in the heap or String Pool.
3. Why Did the String Pool Move from PermGen to Heap?
Earlier (Java 6 and below), the String Pool was stored in the PermGen (Permanent Generation), which is a size-limited area.
Problems with PermGen Storage:
- Finite memory (fixed-size space) 64 MB on 32-bit and 82 MB on the 64-bit JVM version.
- OutOfMemoryError (OOM) if too many strings are created.
Solution in Java 7+: Moved String Pool to Heap
- Heap memory is larger and can be garbage-collected efficiently.
- Allows for improved performance and scalability.
4. Best Practices for Memory Optimization in Java using Strings
- Use “string” directly instead of new String(“string”) to take advantage of the String Pool.
- Use intern() for duplicate strings in large-scale applications.
- Use StringBuilder for manipulation instead of String in order not to create unnecessary objects.
- Enable optimizations for memory management using Garbage Collection.
Operations on String in Java
Almost every Java program, from console programs to business programs, uses string manipulation to a large extent. Java contains a rich collection of inbuilt methods in order to deal with frequent string operations in a very effective manner. It is necessary to be aware of these operations for the handling of the following:
Here we will be discussing the 7 most commonly utilized string operations in Java and the way they actually function internally so that you can write bug-free and efficient code.
1. Concatenation
Concatenation is the operation of merging multiple strings into a string. Three major types of concatenation are commonly implemented in Java:
- Using the + operator (simple but not very effective).
- Using the concat() function (more readable but equivalent to +).
- Using StringBuilder (most effective in repetitive concatenation).
a. Using + Operator
The + operator is the simplest and direct string concatenation form. It does create multiple objects in memory and therefore causes performance issues in big applications.
Output:

Performance Issue:
- A new String object is created every time we use +.
- This will use more memory and is even slower, especially in loops.
b. Using concat() Method
The concat() method in Java simply concatenates two strings without changing the original string.
Output:

Key Points:
- The same as the disadvantages of +, as it constructs a new string instead of modifying the existing one.
c. Using StringBuilder
StringBuilder is mutable, i.e., it modifies the same object instead of creating new objects.
Output:

Why Use StringBuilder?
- They are much faster than + and concat() when concatenating strings inside loops.
- They never form duplicate objects and reduce the use of memory.
- Heavily used in real-time applications like handling large files and logs
2. Substring Extraction
A substring in Java is generally a subset of a string. The substring() function allows you to access subsets of a string in an efficient way.
Output:

Key Points:
- Indexing begins at 0.
- The end index is an exclusive index, and it will not include the character in the last index.
Performance Tip:
- In previous versions of Java (before Java 7), substring() method used to share the same memory reference.
- Post-Java 7, it does create a new object, so it’s safer but a little memory-hungry.
3. String Length
To find the length of a string, the function length() can be used, and it will return the total length and size of the string.
Output:

This operation also covers special characters, spaces, and punctuation.
4. Extracting Characters (charAt())
The charAt(index) function enables you to find a specific character in a string.
Output:

Warning:
- If the index is outside the range, Java simply throws StringIndexOutOfBoundsException.
5. String Comparison
Comparison between strings in Java is a very important operation. Different methods produce different behaviors:
a. Using equals()
Output:

Returns true if and only if the strings are equal.
b. Using equalsIgnoreCase() (Overlooking Case Differences)
Output:

This method is very convenient for user authentication, where there is no requirement for case sensitivity.
c. Using compareTo() (Lexicographical Comparison)
Returns:
- 0 -> if both strings are equal.
- -1 -> if s1 < s2.
- +1 -> if s1 > s2.
Output:

6. String Case Conversion
This operation will primarily convert uppercase Strings to lowercase or vice versa.
Output:

It is useful for case-insensitive search and validation of user inputs.
7. Finding a Character or Substring
a. Verifying if a String Contains a Specific Word
Output:

Returns true if found, else false.
b. Finding the First Occurrence of a Substring (indexOf())
Output:

Returns -1 if not found.
Strings Methods in Java
Below is a table of the most used String methods in Java for your reference:
Method |
Description |
Example Usage |
length() |
Returns the length of the string. |
“Java”.length() -> 4 |
charAt(index) |
Retrieves the character at a specified index. |
“Java”.charAt(1) -> ‘a’ |
substring(start, end) |
Extracts a substring from start to end (exclusive). |
“Hello”.substring(1, 4) -> “ell” |
contains(seq) |
Checks if a sequence of characters is present. |
“Java is fun”.contains(“Java”) -> true |
equals(str) |
Compares two strings (case-sensitive). |
“Java”.equals(“java”) -> false |
equalsIgnoreCase(str) |
Compares strings, ignoring case. |
“Java”.equalsIgnoreCase(“java”) -> true |
toLowerCase() |
Converts all characters to lowercase. |
“HELLO”.toLowerCase() -> “hello” |
toUpperCase() |
Converts all characters to uppercase. |
“hello”.toUpperCase() -> “HELLO” |
trim() |
Removes leading and trailing spaces. |
” Java “.trim() -> “Java” |
replace(old, new) |
Replaces occurrences of a character or substring. |
“abc”.replace(‘a’, ‘z’) -> “zbc” |
split(regex) |
Splits the string based on a regex pattern. |
“a,b,c”.split(“,”) -> [“a”, “b”, “c”] |
startsWith(prefix) |
Checks if the string starts with a specific prefix. |
“Java”.startsWith(“J”) -> true |
endsWith(suffix) |
Checks if the string ends with a specific suffix. |
“Java”.endsWith(“a”) -> true |
indexOf(str) |
Finds the first occurrence of a substring. |
“hello”.indexOf(“l”) -> 2 |
lastIndexOf(str) |
Finds the last occurrence of a substring. |
“hello”.lastIndexOf(“l”) -> 3 |
isEmpty() |
Checks if the string is empty. |
“”.isEmpty() -> true |
concat(str) |
Concatenates two strings. |
“Java”.concat(” Programming”) -> “Java Programming” |
Best Practices for Using Strings in Java
- Use StringBuilder if you want to manipulate strings instead of String because String is immutable, and it creates new objects with every manipulation.
- Use strings with.equals(), never ==, because == will compare object references and not the content itself.
- Don’t use + in a loop to concatenate strings because it creates a lot of unnecessary String objects. Use StringBuilder.append() instead.
- Use toLowerCase(Locale.ROOT) and toUpperCase(Locale.ROOT) to avoid locale-sensitive case conversion differences.
- Prefer strip() over trim() (Java 11+) since it handles Unicode whitespace more correctly. Use stripLeading() and stripTrailing() where they apply.
- Use intern() on strings that are used multiple times so they are stored in the String Pool and save memory.
Conclusion
With this, we have concluded this Java Strings Tutorial, where you have learned that String is a core element of Java and is very important for data manipulation and text processing. You have learned about String creation, types of strings, memory allocation, crucial methods, and tips for performance enhancement. Immutability, String Pool, and efficient operations are the most crucial concepts to write high-performance Java code. With the help of this Java String Tutorial, you can write cleaner, quicker, and effective Java code and avoid common issues.
Java Strings – FAQs