Strings in Java: Part-1

Strings in Java: Part-1
Strings in Java: Part-1

Introduction

The string is a non-primitive data type. It is implemented as an array of characters in almost all programming languages. But, unlike most programming languages that implement strings as character arrays, Java implements strings as objects of type String.

Java has a predefined String class that represents character strings. All string literals in Java programs, such as “Hello“, are implemented as instances of this class.

Java can provide a comprehensive set of features that simplify string manipulation by implementing strings as built-in objects. It includes methods for comparing two strings, searching for a substring, concatenating two strings, among other things.

To better grasp each concept, this article on Strings in Java is split into two parts. This article includes an introduction to the Java String class, the internal implementation of strings in memory, the reason for the immutability of strings, and some of the peer classes of the Java String class.

The second part of this series covers Special String Operations. Having read this blog, we recommend you to read part-2 as well to ensure a great understanding of this topic.

So, without further ado, Let’s get started!

Creation of Strings in Java

Before diving deep into the working of Strings in Java, Let’s learn about how to create them. 

String objects in Java can be created in one of the two given ways:

  1. By using a string literal
  2. By using a string constructor

By using a string literal

In Java, this is the simplest way to create strings. String literals can be created by using double quotes

For Example:

blog banner 1
String s="Coding Ninjas";

How does this work internally?

To make strings in Java efficient, Java uses the concept of “string constant pool”. The JVM checks the string constant pool whenever we create a string literal. 

A reference to the pooled object is returned if the string already exists in the pool. If the string does not exist, a new string object or instance is created and placed in the string constant pool.

illustrative_diagram
Both stack and heap areas are part of JVM in the above diagram. 

For example:

String obj1="Coding Ninjas";  
String obj2="Coding Ninjas"; //new instance will not be created.

While creating the obj1, JVM will not find any string object having the value “Coding Ninjas” in the string constant pool to create a new object. For obj2, it will find the string with the same value in the pool. Thus no new object will be created, and the reference to the previous instance will be returned.

Note: This method of creating strings in Java is memory efficient.

By string constructor

The String class in Java supports several constructors. When we create a string object using constructors, the JVM creates a new string object outside the string constant pool in the heap area. The literal is placed in the string constant pool, but the variable points to the object in the heap area.

To understand what the preceding paragraph means, look at the diagram below.

For example: 

String s=new String("Coding");
illustrative_diagram
String Constructor

Some important constructors of string class are explained below. 

  1. To create an empty String, the default constructor can be called. 

For example:

String s = new String();
  • It will create an instance of an empty String.
  1. We frequently need to create strings with initial values. 

To create a String with an array of characters, a string class constructor can be used as given below:

Syntax: 

String(char chars[ ])

For example:

char array[] = { 'p', 'i', 'n','k' };

String s = new String(array);

  • This constructor initializes s with the string “pink”.
  1. We can also specify a subrange of a character array as an initializer using the following constructor: 

Syntax:

String(char chars[ ], int beginIndex, int numChars) 

Here, beginIndex specifies the index at which the subrange begins, and numChars specifies the number of characters to use. 

For example: 

char chars[] = { 'c', 'o', 'd', 'i', 'n', 'g' }; 
String s = new String(chars, 2, 4); 
  • This initializes s with the characters ding.
  1. We can create a String object that contains the same character sequence as another String object using a constructor.

Syntax:

String(String obj)
  • Here, obj is a String object. 

For example:

// Construct one string from another.
class MakeString 
{
public static void main(String args[]) 
{
char c[] = {'J', 'a', 'v', 'a'};
String s1 = new String(c);
String s2 = new String(s1);
System.out.println(s1);
System.out.println(s2);
}
}

Output:

Java
Java

As we can see, s1 and s2 contain the exact string.

Note: To handle an array or sequence of characters, Java provides two more classes other than the string class. These classes are StringBuffer, and StringBuilder. We will discuss them in detail in the upcoming section but before that let’s see why string is immutable?

Immutability of Strings in Java

In Java, string objects are immutable, which simply means something that cannot be changed or modified. Once a string object is created, its data or state can’t be modified.

In the given example, Coding is not changed, but a new object has the value CodingNinjas. 

class ImmutableDemo1
{  
public static void main(String args[])
{  
String s="Coding";  
s.concat(" Ninjas");
//concat() appends the string at the end.  
System.out.println(s);
//will print Coding because strings are immutable objects  
 }  
}

Output:

Coding

It is evident in the diagram given below. Here Coding is not changed, but a new object is created having value Coding Ninjas. That is why strings in Java are immutable.

In the given diagram, two objects are created, but the reference variable ‘s’ still refers to “Coding” and not to “Coding Ninjas”.

But if we explicitly assign it, it will refer to the “Coding Ninjas” object.            

For example:

class ImmutableDemo2
{  
public static void main(String args[])
{  
String s="Coding";  
s=s.concat(" Ninjas");  
System.out.println(s);  
  }  
}

Output:

Coding Ninjas

Reason for immutability

An object is considered immutable if its state cannot change after it is constructed. Security, synchronisation, and efficiency are three substantial advantages of making the String class immutable.

 The various reasons for string immutability are listed below.

  1. A string constant pool is used to store string literals. By maintaining only one copy of each String literal in the pool, the JVM reduces the amount of memory allocated to strings. Here, string immutability helps in optimising the memory allocation.
  1. Strings are extensively used to hold sensitive data. As a result, String security is crucial, and the immutability of strings serves this purpose very well.
  1. Strings are thread-safe because they are immutable, which means they can’t be changed when accessed from multiple threads. 
  1. Strings are used in HashMap, HashTable, HashSet, and other hash implementations. Strings are immutable, resulting in the same hashcodes at the time of insertion and retrieval. As a result, collections that use hash implementations perform better when working with String objects.
  1. The string is the most often used data structure, enhancing its performance has a significant impact on the overall performance of the application.

Fellow classes of Java String Class

Java provides a rich library of numerous classes and packages. StringBuffer and StringBuilder are fellow classes of the Java String class. They provide various functionality of strings. String, as we know, allows fixed-length, immutable character sequences, making it less dynamic. These classes on the other hand represent mutable character sequences. 

Let’s look at some of their prominent features and differences.

String Buffer

  • A string buffer is like a String but can be modified. 
  • It contains a sequence of characters, but the size and content of the sequence can be changed via the various methods provided in the class.
  • String buffers are thread-safe. The principal operations on a StringBuffer are the append and insert methods. 
  • Characters and substrings can be placed in the middle or appended to the end of a StringBuffer. To accommodate such changes, StringBuffer automatically expands in size. 
  • String buffer has a predefined capacity. As long as the size of the character sequence does not exceed the capacity, it is not necessary to allocate a new internal buffer array. If the internal buffer overflows, it automatically increases its size.

For example:

StringBuffer s = new StringBuffer("Coding Ninjas");

String Builder

  • StringBuilder objects are similar to String objects, however, they can be changed. 
  • These objects are internally handled as variable-length arrays containing a sequence of characters. Method invocations can change the length and content of the sequence at any time. 
  • String Builder class provides an API compatible with StringBuffer and is used as a replacement for StringBuffer.
  • String builder class is used in preference to StringBuffer as it is faster in terms of implementation. The principal operations on a StringBuilder are the append and insert methods. 
  • Unlike strings, every string builder has a capacity, which is the number of character spaces allocated. It automatically extends to accommodate new string builder additions.

For example:

StringBuilder s = new StringBuilder();
str.append("Codingninjas");

Note: StringBuffer(String str) accepts a String argument that sets the initial contents of the StringBuffer object and reserves room for 16 more characters without reallocation.

Thus in the above example, It will produce a string builder with a length of 12 and a capacity of 16.

Note: The append() and insert() methods, which are overloaded to accept data of any type, are the main operations on a StringBuilder that are not available in the String class. 

We discussed these operations in detail in the Special String Operations blog.

Differences between StringBuffer and StringBuilder

Both the classes are analogous, except that StringBuffer is thread-safe by having its methods synchronized. Some of the primary differences and similarities are given in the table below:

StringBufferStringBuilder
StringBuffer is a part of Java since its initial version 1.0StringBuilder is introduced in Java 5.
All the methods of the StringBuffer class are synchronised.Methods are not synchronised in the StringBuffer class.
StringBuffer is safe to use concurrently by multiple threads. It is thread-safe.Instances of StringBuilder are not safe for use by multiple threads. It is not thread-safe.
The performance of StringBuffer is slow.The performance of StringBuffer is fast.
StringBuffer objects are mutable.StringBuilder objects are mutable too.
The storage area used by StringBuffer is heap memory.The storage area used by StringBuilder is also heap memory.

Frequently Asked Questions

What are strings in Java?

The string is a non-primitive data type. It is implemented as a character array in the memory.

What is special about strings in Java?

Strings in Java are not just a non-primitive data type, it is an object of Java String class. It is implemented internally by a char array. Since arrays are unmodifiable, Strings are unmodifiable as well. To change to a String, an entirely new String should be created.

What is the main difference between string and string buffer?

String class is immutable, and StringBuffer class is mutable. A string is slow and consumes more memory. On the other hand, StringBuffer is fast and consumes less memory.

Is string thread-safe in Java?

String is immutable, and that’s why it is also thread-safe. The string can not be used by two threads simultaneously.

Why is string immutable in Java?

Caching, security, synchronisation, and efficiency are all advantages of making the string class immutable. The basic reasons for string immutability are mentioned above.

Key Takeaways

In this tutorial, we learned about Java Strings, how to create them, and various string methods with the help of examples. String class is undoubtedly the special class in Java, and it has a rich library of methods and constructors.

To read more about methods of String class in Java, move to Special String Operations|Part-2 of this tutorial.

If you want to explore primitive data types in Java? Check out this amazing article: Data Types And Identifiers In Java. 

Java is one of the most popular languages. It finds wide applications in Android development and server development. Learning Java in-depth will get you a lucrative placement.

To learn more about Java, take a look at various courses offered by Coding Ninjas. To know more about the best books of Java, check out our blog on 21 Best Java Programming Books for Beginners & Experts.

Happy Learning!