Strings are among the most used data types in any Java program. With that, they come with special support from the Java libraries. Unlike many programming languages that define strings as arrays, Java instead defines strings as objects. In addition, Java strings are immutable. This means they can not be modified after being initialized.
This characteristic of Java strings as immutable objects introduces interesting properties that this Java programming tutorial will explore in detail.
How to Create Strings in Java
There are three ways in which a developer can create a string in Java. The first way is to pass a message to a the String constructor, as shown in the following code snippet: String s1 = new String(“Hello”);
The above statement creates an object s1 of type String and assigns it the value “Hello”.
The second way to create a string in Java is to pass an array of character values to it, as demonstrated below:
char[] p = {'W', 'o', 'r', 'l', 'd'}; String s2 = new String(p);
The third method is to assign a string literal to a variable of type String. Java provides this as a shorthand for the first method shown, since strings are a frequently used data type.
String s3 = "Yeah";
You are likely more familiar with the above syntax since it is the most used one. Later in this article, you will see how the syntaxes shown before differ from the latter in terms of execution.
It is interesting to note that a string literal can be used anywhere a string object can be used. See the example below:
System.out.println("apples".length());
Notice that the apples string literal is used with the length() method. This method is used with string objects to return the length of a string.
Here, it has been used with a string literal and it will still return its character length (for example, 6) to println, without any errors.
Read: How to Print an Array in Java
Interned Strings in Java
Java provides a way to save memory in case you have multiple strings with the same character sequence in your program. It does this by returning the address of a matching string in case it already exists in the memory pool. This is known as string interning.
Consider the Java code example below:
public class Fruits{ public static void main (String args[]){ String s1 = "Mango"; String s2 = new String("Mango"); String s3 = "Mango"; if (s1 == s2) { System.out.println("s1 and s2 have the same reference"); } else{ System.out.println("s1 and s2 have different references"); // this is executed } if (s1 == s3) { System.out.println("s1 and s3 have the same reference"); // this is executed } else{ System.out.println("s1 and s3 have different references");} }}
When s1 is initialized with a string literal, the Java Virtual Machine (JVM) checks if the same string character sequence exists in the memory heap. If an interned object for the string “Mango” already exists, then no new object is created. In this case, no such object exists. Therefore, a new object – s1 – is created.
However, when the new operator is used, a new address space is immediately created. Therefore, s1 and s2 have different references.
When s3 is created using a string initializer, the JVM will check if the string already exists (the same process as with s1). In this case, since the interned object s1 already exists, no new object for s3 is created. Instead, the reference for s1 is returned.
Now would be a good time to mention that the equality operator == is used to compare memory addresses and not character sequences. If you noticed in the example above, the strings s1, s2 and s3 all have the same character sequence (“Mango“).
To check if strings have matching character sequences, you should use the equals() method instead, as shown here:
if (s1.equals(s2)){ // s1 and s2 have the same contents } if (s3.equals(s1)){ // s3 and s1 have the same contents }
By now you must be wondering if Java provides any way of string interning if the string was created using the new keyword. Java does actually provide the intern() method for the String class to do this.
The intern() method takes no argument. When used, it returns the reference of a string object if it already exists; otherwise, a new reference is created:
String str1 = new String("Berry").intern(); String str2 = new String("Berry").intern(); System.out.println(str1== str2); // true
Read: Java Multithreading Explained
StringBuilder and StringBuffer in Java
As mentioned, by default, Java strings are immutable. This means that you can not change a string’s contents once created. Observe the following code where we create a string named s4 and assign it the text value ”colors”. After, we try to change the value of s4 to ”fruits”:
String s4 = "colors"; s4 = "fruits";
The above code would cause your compiler to give off an error, sense you cannot change an immutable data types value. However, Java does provide two classes that you can use to write mutable strings, whose values can be changed. The classes are StringBuilder and StringBuffer. They are both used in a similar way to the String class.
The difference between the two is that StringBuffer provides thread-safety and synchronization while StringBuilder does not. However, StringBuilder has a much better performance because of this. The choice of use ultimately depends on the programmer’s needs and the program environment.
Here is an example of how to create a mutable string in Java using the StringBuilder class:
StringBuilder str1 = new StringBuilder("Java "); // create mutable string, str1 str1.append("Programmer"); // adds another string to str1
The shown example demonstrates how to create a mutable string. The method append() is explained in the code comments; it essentially is used to append another string value to an existing, mutable, string.
Read: An Introduction to JVM Threading Implementation
Summary of Java String Objects
Strings in Java are immutable. This provides many advantages, including consistency across different program states and better multithreaded performance.
Java also provides string interning to enable you to save memory. However, you should not always use intern() if your program does not have many repeated values. This is because the JVM has a limited cache space in the permanent memory pool.