Welcome to “String in Java,” your comprehensive guide to understanding and utilizing the power of String in Java programming. Strings play a fundamental role in Java, serving as a crucial data type for representing and manipulating textual information.
In this article, we will delve into the world of strings in Java, exploring their features, operations, and best practices for working with them effectively. Whether you are a beginner or an experienced Java developer, this guide will provide you with a deep understanding of the String in Java and its associated methods.
What is a String in Java?
String is the most commonly used class in Java.So it is very essential that Java developers have a basic understanding of the tenets of String.
In a nutshell, String in Java is nothing but a sequence of characters. String is a VIP class in Java having the following privileges:
- It is immutable which means it’s contents can’t be modified.
- There is a separate memory space in JVM called String literal pool (String constant pool) wherein the String literals are stored.
- Strings get the benefits of being used like primitives but are internally Objects.For example: Strings can be concatenated using “+” operator like primitives.
Why is String in Java Immutable?
There are multiple reasons which the Java designers kept in mind for making String immutable. Let us look into the reasons:
- Enhancing Security with String in Java: The Java String class plays a vital role in ensuring security in various scenarios. Strings are commonly used as parameters for opening network connections, establishing database connections, and accessing files. By passing sensitive information as immutable strings, such as hostnames or database URLs, we prevent unauthorized access or tampering. The immutability of Java strings provides an additional layer of security, protecting against potential threats and ensuring the integrity of sensitive data.
- Thread Safety and Immutable Java String: The immutability of the Java String class also contributes to thread safety. Immutable objects, like strings, can be freely shared among multiple threads without the need for synchronization. This eliminates concerns related to concurrent modifications and data inconsistencies. Immutable Java strings facilitate safer and more efficient concurrent programming, enhancing the overall stability and reliability of multi-threaded applications.
- String Pool and Immutability in Java: The concept of the string pool, a storage area for commonly used strings, heavily relies on the immutability of Java strings. In the string pool, a single string object can be referenced by multiple variables, ensuring memory efficiency and avoiding duplication. If strings were mutable, modifying one reference would affect all other references, leading to unintended consequences. By maintaining immutability, Java enables efficient string pooling, optimizing memory usage and improving overall performance.
- Caching Hashcode for Performance: The Java String class takes advantage of immutability by caching its hashcode. Once calculated, the hashcode is stored and reused, eliminating the need to recalculate it every time the hashcode method is called. This caching mechanism significantly boosts performance, especially when using strings as keys in data structures like hashmaps. By caching hashcodes, Java strings ensure efficient and fast retrieval of values, enhancing the performance of hash-based data structures.
- Class Loading: The absolutely most important reason that String is immutable is that it is used by the class loading mechanism. Had String been mutable, a request to load “java.io.Writer” could have been changed to load “test.gyan.NewClass”.
What is String literal and String Constant Pool ?
Since String objects are frequently used , Java designers wanted to minimise the creation of lots of String objects.They came up with an idea to cache all String instances created inside double quotes e.g. “Java”. These double quoted literal is known as String literal and the cache which stored these String instances are known as as String pool. Till Java 6 String constant pool is located in permgen space of method area,but after Java 7 onwards its moved to specialised area inside heap area. Earlier since it was in PermGen space, it was always a risk to create too many String object, because its a very limited space, default size 64 MB and used to store class metadata e.g. .class files.Creating too many String literals can cause java.lang.OutOfMemory: permgen space. Now because String pool is moved to a much larger memory space, it’s much more safe.
Creating String in Java : Literal vs new operator
We can create String objects by the following two ways:
1.Using String literal
String str1 = “abc”;
When we create a String using double quotes, JVM looks in the String pool to find if any other String is stored with same value.If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
2.Using new operator
String str = new String(“abc”);
When we use new operator, JVM creates the String object in heap but don’t store it into the String Pool. We can use intern() method to store the String object into String pool.
Important Methods of String Class
Here are some important methods of the Java String class presented with bold formatting:
Method | Description |
---|---|
charAt(int index) | Returns the character at the specified index in the string. |
length() | Returns the length of the string. |
substring(int beginIndex) | Returns a new string that is a substring of the original string, starting from the specified index. |
concat(String str) | Concatenates the specified string to the end of the original string. |
equals(Object obj) | Compares the string with the specified object for equality. |
startsWith(String prefix) | Checks if the string starts with the specified prefix. |
endsWith(String suffix) | Checks if the string ends with the specified suffix. |
toUpperCase() | Converts the string to uppercase. |
toLowerCase() | Converts the string to lowercase. |
replace(char oldChar, char newChar) | Replaces occurrences of a specific character with a new character. |
split(String regex) | Splits the string into an array of substrings based on the specified regular expression. |
indexOf(String str) | Returns the index of the first occurrence of the specified string in the original string. |
trim() | Removes leading and trailing whitespace from the string. |
isEmpty() | Checks if the string is empty (has zero length). |
String interning using intern() method
intern() method of Java String class is used to perform interning i.e creating an exact copy of heap String object in string constant pool. When you call this method on a String object, first it checks whether there exist an object with the same content in the String Constant Pool. If object does not exist in the pool, it will create an object with the same content in the string constant pool and returns the reference of that object. If object exist in the pool then it returns reference of that object without creating a new object.
When you create using String literal, it automatically call intern() method to put that object into String pool,provided it was not present in the pool already. This is another difference between string literal and new string,because in case of new, interning doesn’t happen automatically, until you call intern() method on that object.
String s1 = new String(“Gyan”); // creates the String object in the heap
String s2 = s1.intern(); // creates object in String pool and returns the pool reference
System.out.println(s1 == s2); //Output : false (As s1 points to object in heap whereas s2 points to the object in the String Pool)
System.out.println(s1.equals(s2)); //Output : true
So we can conclude the below:
1) Creating String in heap only : String str = new String(“abc”);
2) Creating string in String pool only: String str = “abc”;
3) Creating string on both heap and string pool:String str = new String(“abc”).intern();
What is the use of interning the string?
Save Memory Space
String pool is also example of Flyweight design pattern.String pool helps in saving a lot of memory space although it takes more time to create the String.If you are using lots of string objects with same content in your code, than it is better to create an intern of that string in the pool. Use that intern string whenever you need it instead of creating a new object in the heap.
Faster Comparison
Assume that there are two string objects s1 and s2 in heap memory and you need to perform comparison of these two objects more often in your code. Then using s1.intern() == s2.intern() will be more fast then s1.equals(s2). Because, equals() method performs character by character comparison where as “==” operator just compares references of objects.
FAQs: String in Java
- Q: What is a String in Java? A: String in Java is a sequence of characters that represents textual data. It is an object of the
String
class and is widely used for manipulating and storing textual information. - Q: How do you create a String in Java? A: There are multiple ways to create a String in Java:
- Using string literals:
String str = "Hello, World!";
- Using the
new
keyword:String str = new String("Hello");
- Using string literals:
- Q: What is the difference between String and StringBuilder/StringBuffer? A: The main difference is that strings are immutable, meaning their values cannot be changed once created, while
StringBuilder
andStringBuffer
are mutable and allow for efficient string manipulation. UseString
when immutability is desired andStringBuilder
/StringBuffer
for frequent string modifications. - Q: How do you concatenate Strings in Java? A: Strings can be concatenated in Java using the
+
operator or theconcat()
method. For example:String result = str1 + str2;
orString result = str1.concat(str2);
- Q: Can you modify a String in Java? A: No, strings are immutable in Java, meaning their values cannot be changed. However, string manipulation operations return new string objects rather than modifying the original string.
- Q: What is String immutability ? A: String immutability means that once a string object is created, its value cannot be changed. Any modification operations on strings create new string objects, ensuring that the original string remains unaltered.
- Q: How do you compare Strings in Java? A: Strings can be compared in Java using the
equals()
method or thecompareTo()
method for lexicographic comparison. For example:boolean isEqual = str1.equals(str2);
- Q: What is the difference between equals() and == when comparing Strings? A: The
equals()
method compares the content of the strings for equality, while the==
operator checks if the references of the strings are the same. Useequals()
for content comparison and==
for reference comparison. - Q: What is String interning in Java? A: String interning is a process in Java where multiple string objects with the same content are represented by a single shared copy. This reduces memory usage and optimizes string comparison operations. It can be achieved using the
intern()
method. - Q: How do you extract substrings from a String in Java? A: You can extract substrings from a string in Java using the
substring()
method, which takes the starting and ending indices as parameters. For example:String sub = str.substring(2, 5);
extracts a substring starting from index 2 and ending at index 5. - Q: How do you check if a string contains a specific character or Substring in Java? A: You can check if a string contains a specific character using the
contains()
method or if it contains a substring using theindexOf()
method. For example:boolean containsChar = str.contains("a");
orint index = str.indexOf("hello");
- Q: How do you split a string into an array of substrings ? A: You can split a string into an array of substrings using the
split()
method, which takes a delimiter as a parameter. For example:String[] substrings = str.split(",");
splits the string using a comma as the delimiter. - Q: How do you remove leading and trailing whitespace from a String in Java? A: You can remove leading and trailing whitespace from a string using the
trim()
method. For example:String trimmed = str.trim();
removes any leading and trailing whitespace fromstr
. - Q: How do you convert a String to a numeric value? A: You can convert a string to a numeric value using parsing methods such as
Integer.parseInt()
,Double.parseDouble()
, etc. For example:int num = Integer.parseInt(str);
convertsstr
to an integer.
Conclusion: String in Java
Throughout this article, we explored various aspects of String in Java, including String creation, concatenation, comparison, manipulation, and conversion. We also discussed important concepts Such as String immutability, memory management, and performance considerations.
Thanks for justifying the title:)
We can get all possible details about String from here. Explanations are very helpful.
In Java7/Java8 String pool is inside Heap not in Metaspace. Also if there is no reference to a String literal, then it becomes eligible for GC 🙂
Now everything got crystal clear. Thank you so much:)
I was browsing about JVM changes in java 8 and based on what I have found till now:
In Java 8, PermGen is completely removed and all its content are moved to separate native memory in the OS called as Metaspace. and hence the OutOfMemoryError due to insufficient PermGen size would never happen anymore.
My query here:
Is the String pool also moved to the metaspace or is it still inside Heap only?
If it is still inside Heap, then does it allow GC (i.e., if a literal has no reference)?
String Pool was moved from PermGen in Java7 itself. In Java7 some of the things of (including String pool) of PermGen were moved to Heap. In Java 8 PermGen was totally removed and replaced with Metaspace.
Thanks for clarifying 🙂
And regarding my second query, I think String pool is inside heap but not inside any of its generation (i.e., Young or Tenured) and hence could not be garbage collected. Is that right?
One confusion regarding the String creation using new operator:
String str = new String(“arg”);
here, new is for creating an object, String(“arg”) is for immediately initializing the object by calling its parameterized constructor with a String argument.
So my doubt is:
For calling the constructor with a String argument, is it first creating a literal i.e., “arg” and then passing it as argument? In that case, two objects are created: one in String pool (i.e., literal “arg”) & one in Heap (i.e., using new operator).
But if that happens, then there will be no use of intern() and also creating String object using new operator will become meaningless as the GC will only destroy the object not the literal.
I am totally confused here, please help 🙂
String str = new String(“arg”);
It only creates the Object only in Heap…nothing in String Pool.
Only when intern is called, it creates the String literal in String Pool (only if it is not there) and returns the reference to String literal in the pool.
1) Creating String in heap only : String str = new String(“abc”);
2) Creating string in String pool only: String str = “abc”;
3) Creating string on both heap and string pool:String str = new String(“abc”).intern();
Thank you. I am now able to get a clear understanding on that concept.