Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The return of String.intern() explained

Consider:

String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?

String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false

String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false

I got confused why they are resulting differently by the returned value of String.intern() which says:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

Especially after these two tests:

assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
    new StringBuilder("jav").toString() == "jav");

I once read a post talking about some special strings interned before everything else, but it's a real blur now.

If there are some strings pre-interned, is there a way to get kind of a list of them? I am just curious about what they can be.


Updated

Thanks to the help of @Eran and @Slaw, I finally can explain what just happened there for the output

true
true
false
false
false
  1. Since "Cattie & Doggie" doesn't exist in the pool, s1.intern() will put the current object reference to the pool and return itself, so s1.intern() == s1;
  2. "Cattie & Doggie" already in the pool now, so string literal "Cattie & Doggie" will just use the reference in pool which is actually s1, so again we have true;
  3. new StringBuilder().toString() will create a new instance while "java" is already in the pool and then the reference in pool will be returned when calling s2.intern(), so s2.intern() != s2 and we have false;
  4. new String() will also return a new instance, but when we try to s3.intern(), it will return the previously stored reference in the pool which is actualy s1 so s3.intern() != s3 and we have false;
  5. As #2 already discussed, String literal "Cattie & Doggie" will return the reference already stored in the pool (which is actually s1), so s3 != "Cattie & Doggie" and we have false again.

Thanks for @Sunny to provide a trick to get all the interned strings.

like image 271
Hearen Avatar asked Mar 13 '19 06:03

Hearen


People also ask

What does string intern () method do?

The method intern() creates an exact copy of a String object in the heap memory and stores it in the String constant pool. Note that, if another String with the same contents exists in the String constant pool, then a new object won't be created and the new reference will point to the other String.

What is String intern () When and why should it be used?

String Interning is a method of storing only one copy of each distinct String Value, which must be immutable. By applying String. intern() on a couple of strings will ensure that all strings having the same contents share the same memory.

What is the use of intern () in Java?

The Java String intern() method returns a canonical representation of the string object. Here, string is an object of the String class.

What is the use of the intern () method A It returns the existing string from memory B it creates a new string in the database C it modifies the existing string in the database?

The intern() method creates an exact copy of a string that is present in the heap memory and stores it in the String constant pool if not already present. If the string is already present, it returns the reference. The intern() method helps to save memory space and reuse it efficiently at the cost of time.

What does the Java String class intern () method return?

The Java String class intern () method returns the interned string. It returns the canonical representation of string. It can be used to return string from memory if it is created by a new keyword.

When should we use intern method of string on string constants?

As explained in this When should we use intern method of String on String constants post that String literals are automatically pooled but for object constructed using new are not, so for that intern method is used. But even if we use intern method a new object will be created, then what is the use of intern method?

Does a string literal always invokes the intern () method?

1) A string literal always invokes the intern () method, whether one mention the intern () method along with the string literal or not. For example,

What is string interning and how does it work?

By applying String.intern () on a couple of strings will ensure that all strings having the same contents share the same memory. For example, if a name ‘Amy’ appears 100 times, by interning you ensure only one ‘Amy’ is actually allocated memory. Attention reader! Don’t stop learning now.


2 Answers

s2.intern() would return the instance referenced by s2 only if the String pool didn't contain a String whose value is "java" prior to that call. The JDK classes intern some Strings before your code is executed. "java" must be one of them. Therefore, s2.intern() returns the previously interned instance instead of s2.

On the other hand, the JDK classes did not intern any String whose value is equal to "Cattie & Doggie", so s1.intern() returns s1.

I am not aware of any list of pre-interned Strings. Such a list will most likely be considered an implementation detail, which may vary on different JDK implementations and JDK versions, and should not be relied on.

like image 83
Eran Avatar answered Sep 19 '22 21:09

Eran


When the intern() method is invoked on a String object it looks the string contained by this String object in the pool, if the string is found there then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

So java string must already be in the pool. hence it is giving false.

You can print all strings in pool

How to print the whole String pool?

Here is an example to get all string if you are using openjdk.

like image 45
Sunny Avatar answered Sep 22 '22 21:09

Sunny