Question

The following segment of code interns a string.

String str1="my";
String str2="string";
String concat1=str1+str2;
concat1.intern();

System.out.println(concat1=="mystring");

The expression concat1=="mystring" returns true because concat1 has been interned.


If the given string mystring is changed to string as shown in the following snippet.

String str11="str";
String str12="ing";
String concat11=str11+str12;
concat11.intern();

System.out.println(concat11=="string");

The comparison expression concat11=="string" returns false. The string held by concat11 doesn't seem to be interned. What am I overlooking here?

I have tested on Java 7, update 11.


EDIT:

The whole code:

package test;

public final class Test
{
    public static void main(String... args)
    {
        String str11="my";
        String str12="string";
        String concat11=str11+str12;
        concat11.intern();
        System.out.println(concat11=="mystring");

        String str1="str";
        String str2="ing";
        String concat1=str1+str2;
        concat1.intern();
        System.out.println(concat1=="string");
    }
}
Was it helpful?

Solution 2

When you use intern() on string that wasn't in string pool earlier this string will be placed there and every next literal will use reference to it.

But if there is already some literal in strings pool and you will try to invoke intern() on newly created string object with same characters, it will not be placed in pool but will only return reference to string from pool. Also it will not change reference to original string on which intern was invoked.

Since Java loads and executes some code before executing main method there is a chance that some literals will be placed in string pool before execution of main code.
For example String pool will contain literals such as "UTF-8", "charset", "charsetName", which may come from java.lang.String, or java.nio.charset.Charset classes. It seems that "string" literal is one of them (I am not sure where exactly it was added to String pool).

So when you are invoking

String str11="str";
String str12="ing";
String concat11=str11+str12;
concat11.intern();

your intern will not put "string" from concat11 in string pool because there is one already there and other "string" literals (like these you used in =="string" part) will be using the one from string pool, not from concat11.

Lets test this theory:

String s = "ABCdef";// this string will be placed in 
                    // string pool before rest of code

String str1 = "ABC";
String str2 = "def";
String concat1 = str1 + str2;
concat1.intern();//this will only return reference to literal from pool

System.out.println(concat1 == "ABCdef");//false


// here we don't have any "ABcd" literal in pool yet
String strA = "AB";
String strB = "cd";
String concatAB = strA + strB;
concatAB.intern();//so this will put String object from concatAB to pool
System.out.println(concatAB == "ABcd");//and "ABcd" literal will use same object

output

false
true

OTHER TIPS

If you run both of these snippets in the same program, then concat1.intern() will add concat1 to the pool of interned strings. But concat11.intern() won't add anything to the pool, because "string" is already in the pool (from str2). So your last comparison is comparing concat11 to str2 - and these are not the same object.

From the Javadoc at http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/String.html

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.

When a string is created and if the string already exists in the pool, the reference of the existing string will be returned, instead of creating a new object and returning its reference.

refer this site http://java.dzone.com/articles/why-string-immutable-java

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top