String pool and heap storage

String is a sequence of characters, for e.g. “Hello” is a string of 5 characters. In java, string is an immutable object which means it is constant and can cannot be changed once it has been created.

Finding a String Within Another String

To check whether a particular String a is being contained in a String b or not, we can use the method
String.contains() with the following syntax:

b.contains(a); // Return true if a is contained in b, false otherwise

The String.contains() method can be used to verify if a CharSequence can be found in the String. The method looks for the String a in the String b in a case-sensitive way.

String str1 = "Hello World";
String str2 = "Hello";
String str3 = "helLO";

System.out.println(str1.contains(str2)); //prints true
System.out.println(str1.contains(str3)); //prints false

To find the exact position where a String starts within another String, use String.indexOf():

String s = "this is a long sentence";
int i = s.indexOf('i');      // the first 'i' in String is at index 2
int j = s.indexOf("long");   // the index of the first occurrence of "long" in s is 10
int k = s.indexOf('z');      // k is -1 because 'z' was not found in String s
int h = s.indexOf("LoNg");  // h is -1 because "LoNg" was not found in String s

The String.indexOf() method returns the first index of a char or String in another String. The method returns -1 if it is not found.

Note: The String.indexOf() method is case sensitive.

Example of search ignoring the case:

String str1 = "Hello World";
String str2 = "wOr";
str1.indexOf(str2);                              // -1
str1.toLowerCase().contains(str2.toLowerCase()); // true
str1.toLowerCase().indexOf(str2.toLowerCase());  // 6

String pool and heap storage

Like many Java objects, all String instances are created on the heap, even literals. When the JVM finds a String literal that has no equivalent reference in the heap, the JVM creates a corresponding String instance on the heap
and it also stores a reference to the newly created String instance in the String pool. Any other references to the same String literals are replaced with the previously created String instance in the heap.

Let’s look at the following example:

class Strings
     public static void main (String[] args)
        String a = "alpha";
        String b = "alpha";
        String c = new String("alpha");
        //All three strings are equivalent
        System.out.println(a.equals(b) && b.equals(c));
       //Although only a and b reference the same heap object
       System.out.println(a == b);
       System.out.println(a != c);
       System.out.println(b != c);

The output of the above is:


When we use double quotes to create a String, it first looks for String with same value in the String pool, if found it just returns the reference else it creates a new String in the pool and then returns the reference.

Related Article: Substrings in Java

However using a new operator, we force String class to create a new String object in heap space. We can use the intern() method to put it into the pool or refer to other String objects from the string pool having the same value.

The String pool itself is also created on the heap.
Version < Java SE 7

Before Java 7, String literals were stored in the runtime constant pool in the method area of PermGen, which had a fixed size.

The String pool also resided in PermGen.

In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with
the other objects created by the application. This change will result in more data residing in the main Java heap, and fewer data in the permanent generation, and thus may require heap sizes to be adjusted. Most
applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.

Leave a Comment