Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
Strings are one of the most fundamental and widely used data types in Java. They represent sequences of characters and are essential for handling text-based data. From basic text manipulation to complex algorithms, strings play a crucial role in almost every Java application. Understanding how to effectively work with strings is vital for any Java programmer. In this blog, we'll dive deep into the world of strings in Java.
In Java, a String is an object that represents a sequence of characters. Strings are used extensively to store and manipulate text data. They are immutable, meaning once a String object is created, its value cannot be changed. This immutability is crucial for performance and security reasons, especially when strings are used in multi-threaded environments.
Strings in Java are represented by the java.lang.String class, which provides numerous methods for string manipulation, including comparison, searching, and substring extraction. Because strings are so fundamental, the Java language provides special syntax for creating and manipulating them, making it easy to work with text data.
Example of Java String
To illustrate how strings work in Java, let's look at a simple example:
Java
Java
public class StringExample { public static void main(String[] args) { // Creating a String String greeting = "Hello, World!";
Original String: Hello, World!
Concatenated String: Hello, World! Welcome to Java programming.
Length of String: 13
First Character: H
Substring: World
Strings are equal: true
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:
By using a string literal
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:
String s="Coding Ninjas";
How does this work internally?
To make strings in Java efficient, Java uses the concept of "string constant pool”. The JVMchecks 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.
Note: 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.
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");
Some important constructors of string class are explained below.
a. 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.
b. 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”.
c. 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.
d. 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:
Java
Java
// 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); } }
You can also try this code with Online Java Compiler
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?
Extracts a substring from the string between the specified indices.
contains(CharSequence s)
Checks if the string contains the specified sequence of char values.
equals(Object another)
Compares two strings for content equality.
isEmpty()
Checks if the string is empty (length is 0).
toLowerCase()
Converts all of the characters in the string to lower case.
toUpperCase()
Converts all of the characters in the string to upper case.
trim()
Removes whitespace from both ends of the string.
replace(char oldChar, char newChar)
Replaces all occurrences of the specified old character with the specified new character.
startsWith(String prefix)
Checks if the string starts with the specified prefix.
endsWith(String suffix)
Checks if the string ends with the specified suffix.
split(String regex)
Splits this string around matches of the given regular expression.
indexOf(int ch)
Returns the index of the first occurrence of the specified character.
lastIndexOf(int ch)
Returns the index of the last occurrence of the specified character.
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.
Java
Java
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 } }
You can also try this code with Online Java Compiler
It is evident in the diagram given below. Here Coding is not changed, but a new object is created having the 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:
Java
Java
class ImmutableDemo2 { public static void main(String args[]) { String s="Coding"; s=s.concat(" Ninjas"); System.out.println(s); } }
You can also try this code with Online Java Compiler
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.
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.
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.
Strings are thread-safe because they are immutable, which means they can't be changed when accessed from multiple threads.
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.
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:
Let’s move to the frequently asked questions on this topic.
In Java, memory management for String objects is an essential aspect, given their immutable nature and frequent usage in applications.
1. String Literal:
Allocated in the String Pool.
Example: String str = "Hello";
Optimized for memory efficiency by reusing existing instances.
2. String Object:
Allocated in the heap memory.
Example: String str = new String("Hello");
Ensures a new object creation every time.
3. Interned String:
Moves a heap string to the String Pool.
Example: String internedStr = str.intern();
Benefits from memory efficiency like literals.
Frequently Asked Questions
What is special about strings in Java?
Strings in Java are not just a non-primitive data type, it is an object of the 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.
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.
What data type is a string in Java?
In Java, a string is an object of the String class, which is part of the java.lang package.
Conclusion
In this tutorial, we learnt about Java Strings, how to create them, and various string methods with the help of examples. String class is undoubtedly a special class in Java, and it has a rich library of methods and constructors. 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 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 problem - Longest String Chain