Why the classname contradicts with interned string comparison using "=="? - java

class helloworld
{
public static void main(String args[]) {
String str1="hello";
String str2="world";
String str=str1+str2;
str.intern();
System.out.println(str=="helloworld");
}
}
o/p: false
After Executing the program it produces false as output.if equals() is used instead of "==" it returns true.why so?
2.In this case after changing classname it produces true as output.
class main
{
public static void main(String args[]) {
String str1="hello";
String str2="world";
String str=str1+str2;
str.intern();
System.out.println(str=="helloworld");
}
}
o/p:true
Why the contradiction occurs b/w interned string comparison using "==" with classname (in case of comparison string name is used as classname)?

The reason is that in the first example, the string "helloworld" is already in the string pool, on account of its being the name of the class. So interning it doesn't add anything to the string pool. So str won't be the interned value, and the comparison will be false.
In the second example, str.intern() actually adds str to the string pool, because "helloworld" is not already there. Then, when the "helloworld" literal is encountered, the string object that's actually used is the one that's in the string pool. That's just str, so the comparison will be true.

String is immutable. You must use the return value of str.intern(). Just calling str.intern() and ignoring the return value does nothing.
str = str.intern();

Supplementing answers, here a nice articles about intern()
English: https://weblogs.java.net/blog/2006/06/26/all-about-intern
Russian: http://habrahabr.ru/post/79913/

String in an immutable Object. And as of intern() function as per javadoc
When the intern method is invoked, if the pool already contains a
string equal to this <code>String</code> object as determined by
the {#link #equals(Object)} method, then the string from the pool is
returned. Otherwise, this <code>String</code> object is added to the
pool and a reference to this <code>String</code> object is returned.
So you must assign the return value Eg string = string.intern();
As for your output it should be true irrespective of your class name because as mentioned above it has nothing to do with calling intern().

Related

Reference to which String object is returned from the pool when calling intern()

The Java Language Specification states that
When the intern method is invoked, if the pool already contains a
string equal to this String object as determined by the
equals(java.lang.Object) method, then the string from the pool is
returned
In the following code snippet:
class StringPoolTest {
public static void main(String[] args) {
String first = "string";
String second = new String("string");
String third = "string".intern();
System.out.println(System.identityHashCode(first));
System.out.println(System.identityHashCode(second));
System.out.println(System.identityHashCode(third));
}
}
Output:
989184670
268130470
989184670
I added a String object first to the pool (assigning a String literal to the reference) and explicitly created second using a String constructor.
There are now two identical character sequences in the pool.
I wanted to see which one would be returned when calling intern. Since the method hashCode is overridden for the class String, I used System.identityHashCode to see exactly which two String references were the same.
Clearly, intern returned the reference to the object created using a String literal. Why is this so? Are there any rules regarding which reference is returned in the case of multiple identical String objects in the pool?
When a string literal(without using new Operator) is created, the JVM checks whether that String exists in the internal list or not. If it already exists in the list, then it does not create a new String and it uses reference to the existing String Object.
JVM does this type of checking internally for String literal but not for String object, which it creates through 'new' keyword i.e. using new always a new string is returned.

string constant pool using + operator

public class Strings
{
public static void main(String ads[])
{
String a = "meow";
String ab = a + "deal";
String abc= "meowdeal";
System.out.println (ab==abc);
}
}
why output is false?
In this program ab is created in string literal and then abc created but why ab and abc not refer to the same memory in string constant pool ,because before creating abc it search in string constant pool for String meowdeal.
Java only pools strings it knows about at compile time; string constants and constant string expressions. a is a local variable, so a + "deal" is a string expression that isn't evaluated until runtime (even though you looking at it can see that it should be constant). The Java compiler doesn't know it's a constant expression, and doesn't put it in the pool. It performs the string concatenation at runtime, resulting in a different object than any in the pool.
I'll explain what's happening:
public class Strings {
public static void main(String ads[]) {
String a = "meow"; // new string created
String ab = a + "deal"; // again a new string created. Reference different.
String abc = "meowdeal"; // a whole new string.
System.out.println(ab == abc);// even though the values are same, reference is different. For value equality, use .equals()
}
}
Your question implies that you expect Java to check the result of every string concatenation to see if there is a matching string in the string constant pool - but this would be grossly inefficient. String concats are always new objects unless all the strings are compile-time constants.
If you really want to compare the strings using == you need to intern the constructed string like so:
ab=(a+"deal").intern();
However this would be for a very specific use case and very uncommon.
Note that this is a different case from when two constants are concatenated; given "ab"+"cd" the compiler is required to resolve the expression to "abcd" and pool the result. The same would be true if one or both of the values are compile-time constants, static final ....

Regarding the role of intern() method

I have made the code but please tell the functionality of the intern() method of String class , does it try to bring the pool object address and memory address on the same page?
I have developed the below code :
public class MyClass
{
static String s1 = "I am unique!";
public static void main(String args[])
{
String s2 = "I am unique!";
String s3 = new String(s1).intern();// if intern method
is removed then there will be difference
// String s3= new String("I am unique!").intern();
System.out.println("s1 hashcode -->"+s1.hashCode());
System.out.println("s3 hashcode -->"+s3.hashCode());
System.out.println("s2 hashcode -->"+s2.hashCode());
System.out.println(s1 == s2);
System.out.println("s1.equals(s2) -->"+s1.equals(s2));
/* System.out.println("s1.equals(s3) -->"+s1.equals(s3));
System.out.println(s1 == s3);
System.out.println(s3 == s1);
System.out.println("s3-->"+s3.hashCode());*/
// System.out.println(s3.equals(s1));
}
}
Now what's the role of the above intern() method?
As the hashCodes() are the sames, please explain the role of intern() method.
Thanks in advance.
Since operator== checks for identity, and not equality, System.out.println(s1 == s3); (which is commented out) will yield true only if s1 and s3 are the exact same objects.
The method intern() makes sure that happens, since the two strings - s1 and s3 equal each other, by assigning their intern() value, you make sure they are actually the same objects, and not two different though equal objects.
as the javadocs say:
It follows that for any two strings s and t, s.intern() == t.intern()
is true if and only if s.equals(t) is true.
p.s. you do not invoke intern() on s1, because it is a String literal - and thus already canonical.
However, it has no affect on s1 == s2, since they are both string literals, and intern() is not invoked on neither of them.
From the String.intern() Javadoc
A pool of strings, initially empty, is maintained privately by the class String.
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.
It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.
Returns:
a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
Do you have a more specific doubt which is not covered by the Javadoc?
.intern() ensures that only one copy of the unique String is stored. So, multiple references to the same interned String will result in the same hashCode() as the hashing is being applied to the same String.
This method returns a canonical representation for the string object. It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.
Returns a canonical representation for the string object.
refer http://www.tutorialspoint.com/java/java_string_intern.htm
If you call the intern method of this String object,
str = str.intern();
The JVM will check whether the String pool maintained by the JVM contains any String objects with the same value as the str object with the equals method returning true.
If the JVM finds such an object, then the JVM will return a reference to that object present in the String pool.
If no object equal to the current object is present in the String pool, then the JVM adds this string into the String pool and returns its reference to the calling object.
The JVM adds the object to the String pool so that the next time when any string object calls the intern method, space optimization can be done if both of these strings are equal in value.
You can check the working of intern method using the equals and == operators.
refer : http://java-antony.blogspot.in/2007/07/string-and-its-intern-method.html
String.intern() canonicalize strings in an internal VM string pool. It ensure that there is only one unique String object for every different sequence of characters. Then those strings can be compare by identity (with operator ==), instead of equality (equals()).
For example :
public class Intern{
public static void main(String[]args){
System.out.println(args[0].equals("")); //True if no arguments
System.out.println(args[0] == ""); //false since there are not identical object
System.out.println(args[0].intern() == ""); //True (if there are not multiple string tables - possible in older jdk)
}
}
So, if two Strings are equals (s1.equals(s2) is true) then s1.intern() == s2.intern() is true.

Checking For Equal Instances of 2 Different (Included Example)

I use the == in the code below and prints out "Equals!", why? Can someone explain why these two different strings a and b are equal?
public class test
{
public static void main()
{
String a = "boy";
String b = "boy";
if(a == b)
{
System.out.println("Equals!");
}
else
{
System.out.println("Does not equal!");
}
}
}
This is due to String interning.
Java (The JVM) keeps a collection of String literals that is uses to save memory. So, whenever you create a String like so:
String s = "String";
Java 'interns' the string. However, if you create the String like so:
String s = new String("String");
Java will not automatically intern the String. If you created your strings this way, your code would produce different results.
A quick Google search reveals lots of good resources regarding String interning.
This article will explain it in details:
What is the difference between == and equals() in Java?
After the execution of String a =
“boy”; the JVM adds the
string “boy” to the string
pool and on the next line of the code, it
encounters String b = ”boy” again; in this case the JVM already
knows that this string is already
there in the pool, so it does not create a
new string. So both strings a and b point to the same string what means they
point to the same reference.
String a = "boy"; will create a new string object with value ("boy"), place it in the string pool and make a refer to it.
When the interpreter sees String b = "boy";, it first checks to see if string "boy" is present in the string pool, since it is present, no new object is created and b is made to refer to the same object that a is referring to.
Since both references contain the same content they pass the equality test.
Because the run time will have a string pool and when you need to assign a new constant string, the run time look inside the pool, if the pool contains it, then they set the variable point to the same String object inside the pool.
But you should never depends on this to check for content string equals. You should use the method: equals
Whenever we create a string like below :
String str1 = "abc";
String str2 = "abc";
JVM will check the str2 = "abc" in the string constant pool, if it is present then it wont create a new String instead it point to the string one in the string constant pool.
But in case of this String str = new String("abc"); it will always create a new String Object but we can use intern() function to force JVM to look into the string constant pool.
As rightly explained above, in the case of '==' comparison, the runtime will look into the String pool for the existence of the string. However, it very much possible that during garbage collection, or during memory issues, the virtual machine might destroy the string pool. The "==" operator therefor might or might not return the correct value.
Lesson - Always use equals() for comparison.

Java == for String objects ceased to work?

public class Comparison {
public static void main(String[] args) {
String s = "prova";
String s2 = "prova";
System.out.println(s == s2);
System.out.println(s.equals(s2));
}
}
outputs:
true
true
on my machine. Why? Shouldn't be == compare object references equality?
Because String instances are immutable, the Java language is able to make some optimizations whereby String literals (or more generally, String whose values are compile time constants) are interned and actually refer to the same (i.e. ==) object.
JLS 3.10.5 String Literals
Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions -are "interned" so as to share unique instances, using the method String.intern.
This is why you get the following:
System.out.println("yes" == "yes"); // true
System.out.println(99 + "bottles" == "99bottles"); // true
System.out.println("7" + "11" == "" + '7' + '1' + (char) (50-1)); // true
System.out.println("trueLove" == (true + "Love")); // true
System.out.println("MGD64" == "MGD" + Long.SIZE);
That said it needs to be said that you should NOT rely on == for String comparison in general, and should use equals for non-null instanceof String. In particular, do not be tempted to intern() all your String just so you can use == without knowing how string interning works.
Related questions
Java String.equals versus ==
difference between string object and string literal
what is the advantage of string object as compared to string literal
Is it good practice to use java.lang.String.intern()?
On new String(...)
If for some peculiar reason you need to create two String objects (which are thus not == by definition), and yet be equals, then you can, among other things, use this constructor:
public String(String original) : Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.
Thus, you can have:
System.out.println("x" == new String("x")); // false
The new operator always create a new object, thus the above is guaranteed to print false. That said, this is not generally something that you actually need to do. Whenever possible, you should just use string literals instead of explicitly creating a new String for it.
Related questions
Java Strings: “String s = new String(”silly“);”
What is the purpose of the expression “new String(…)” in Java?
JLS, 3.10.5 => It is guaranteed that a literal string object will be reused by any other code running in the same virtual machine that happens to contain the same string literal
If you explicitly create new objects, == returns false:
String s1 = new String("prova");
String s2 = new String("prova");
System.out.println(s1 == s2); // returns false.
Otherwise the JVM can use the same object, hence s1 == s2 will return true.
It does. But String literals are pooled, so "prova" returns the same instance.
String s = "prova";
String s2 = "prova";
s and s2 are literal strings which are pointing the same object in String Pool of JVM, so that the comparison returns true.
Yes, "prova" is stored in the java inner string pool, so its the same reference.
Source code literals are part of a constant pool, so if the same literal appears multiple times, it will be the same object at runtime.
The JVM may optimize the String usage so that there is only one instance of the "equal" String in memory. In this case also the == operator will return true. But don't count on it, though.
You must understand that "==" compares references and "equals" compares values. Both s and s1 are pointing to the same string literal, so their references are the same.
When you put a literal string in java code, the string is automatically interned by the compiler, that is one static global instance of it is created. Or more specifically, it is put into a table of interned strings. Any other quoted string that is exactly the same, content-wise, will reference the same interned string.
So in your code s and s2 are the same string
Ideally it should not happen ever. Because java specification guarantees this. So I think it may be the bug in JVM, you should report to the sun microsystems.

Categories