Demystifying the Java String Class: Everything You Need to Know

Immutability , String Pool , StringBuilder , StringBuffer & more .

Hamza Nassour
Javarevisited
5 min readFeb 11, 2023

--

In the world of programming, text manipulation is an essential part of many applications. As a Java developer, the String class is an invaluable tool that enables you to work with text data efficiently and effectively .

The String Class in Java

In Java, the String class is a class that represents character sequences. The String class is immutable, which means that once a String object is created, its value cannot be changed. This is a fundamental aspect of the String class .

Important String Methods

The String class has several methods that allow us to manipulate and access the characters within a String object. Some of the most commonly used methods include:

length()

length() method used to return the number of characters in the String object.

Example:

String name = "John";
int length = name.length();
System.out.println(length); //4

charAt()

charAt() method used to return the character at the specified position within a string .

char charAt(int  index)

Example:

String name = "John Doe";
char character = name.charAt(0);
System.out.println( character); //J

indexOf()

returns the index for a given character (return -1 if it can’t find the char or the string ).

In the java String class there are several variations of the indexOf method , that we can use to find the index of a character or a substring within a string . Here are the most commonly used variations of the indexOf :

int indexOf(char ch)
int indexOf(char ch, index fromIndex)
int indexOf(String str)
int indexOf(String str, index fromIndex)

Note: Please keep in mind that, unlike charAt, indexOf will not throw an exception, it will return -1 instead

Note : The fromIndex parameter is used to specify the starting point for Java's search .

Example :

String string = "hamza";
System.out.println(string.indexOf('h')); // 0
System.out.println(string.indexOf("za")); // 3
System.out.println(string.indexOf('a', 3)); // 4
System.out.println(string.indexOf("ha", 5));// -1

substring()

returns a new String object that is a part of the original String object.

The method signature :

int substring(int beginIndex)
int substring(int beginIndex, int endIndex)

Example :

String sentence  = "java programming";
String java = sentence.substring(0, 4); //java

Note: Please keep in mind that the end index is exclusive (for example, sentence.substring(0, 4) returns a string that goes up to but does not include the character at index 4).

toLowerCase() & toUpperCase()

returns a new String object that contains the original String object’s characters in lower case / upper case .

The method signatures are as follows :

String toLowerCase( )
String toUpperCase( )

Example :

String name = "HAMZA nassour ";
String lowerCase = name.toLowerCase();
String upperCase = name.toUpperCase();
System.out.println("The lower case string is: " + lowerCase); // hamza nassour
System.out.println("The upper case string is: " + upperCase); // HAMZA NASSOUR

equals() & equalsIgnoreCase()

equals() compares the contents of two String objects and returns a boolean indicating whether they are equal or not.

Example:

String name1 = "John Doe";
String name2 = "John Doe";
boolean isEqual = name1.equals(name2);
System.out.println("The strings are equal: " + isEqual);

Note : the equalsIgnoreCase() method is the same as equals() method with one exception is that method don’t care about the cases ( hamza == HAMZA for the equalsIgnoreCase() ).

System.out.println("hamza".equalsIgnoreCase("HAMZA"));  //true

startsWith() & endsWith() .

startsWith()/endsWith() Is a method that checks whether a string starts/end with a given substring or not , return a boolean value .

For example,

"hamza".startsWith("ha")  //true
"hello".startsWith("hi") // false.
"hamza".endsWith("a") //true
"hello".endsWith("za") // false.

Note : There are some other interesting methods that we have not covered, but you can explore them in the official documentation. here

The String Pool Constant

In Java, the String pool is a special area of memory where all of the constant String objects are stored. The JVM automatically places all constant String literals in the String pool. This means that if two String objects have the same contents, they will refer to the same object in the String pool.

Example:

String name1 = "John Doe";
String name2 = "John Doe";
System.out.println(name1 == name2); // True

The main purpose of the String Pool is to optimize memory usage by ensuring that there is only one instance of each unique string literal in the system.

Note : when we Use the String Constructor to construct our Strings they will not belongs to the String pool (String str = new String(“hamza”) str is considered as an object and it will be created in the heap area ).

StringBuilder & StringBuffer

StringBuilder (introduced in java 5) is a class in Java that allows for efficient manipulation of strings. Unlike regular strings, which are immutable, StringBuilder can be modified without creating a new object each time.

For example, let’s say you have a loop that is concatenating a large number of characters together:

String result = "";
for (char c = 'a' ; c<= 'z' ; c++) {
result = result+ c ;
}

let’s count the number of string objects created in this example :

In each step of the loop a new object get created ( representing the concatenation ) so the total will be 26 different object and don’t forget the first the empty string in the first line -> 27 object in total which can be very inefficient .

Using StringBuilder can make this code much faster and more memory-efficient :

StringBuilder  result = new StringBuilder();
for (char c = 'a' ; c<= 'z' ; c++) {
result.append(c);
}

This code only creates one StringBuilder object, and the append() method efficiently adds each char to the end of the string. This can be much faster and more memory-efficient than using the string concatenation operator (+) in a loop.

the StringBuilder class in Java is used for creating and manipulating mutable strings. It has many methods for manipulating the content of the string, including append(), insert(), reverse(), delete(), and deleteCharAt() . It also has some of the same methods as the String class, such as charAt() , indexOf(), length(), and substring(), in addition to the method toString() for converting the StringBuilder to a String .

difference between StringBuilder and StringBuffer

The Both class has the same fonctionalities with one difference is that StringBuilder is not thread-safe while StringBuffer is thread-safe .

In other words, if multiple threads are accessing a StringBuilder object simultaneously, there may be synchronization issues, leading to unexpected behavior. On the other hand, if multiple threads are accessing a StringBuffer object simultaneously, the access is synchronized.

Because StringBuffer ensures thread safety through synchronization, it may be slower than StringBuilder, which does not have the overhead of synchronization. Therefore, StringBuilder is generally preferred for single-threaded scenarios, while StringBuffer is more suitable for multi-threaded scenarios.

I hope you guys understood Java Strings & Thank you for reading!

--

--