Java String problems - java

I ran the following program,
String firstString = "String";
String secondString = "String";
String thirdString = new String("String");
System.out.println(firstString == secondString);
System.out.println(firstString == thirdString);
System.out.println(firstString.intern() == thirdString);
System.out.println(firstString.intern() == thirdString.intern());
System.out.println(firstString.intern().equals(thirdString.intern()));
System.out.println(firstString == thirdString);
and my output was
true
false
false
true
true
false
I learnt that the jvm pools string with same content as same strings. Is that right? If thats true then why not the firstString == thirdString return false? Does jvm only pool the string only initialized with :"" and not with new operator?

The pooling relates to string literals only - so firstString and secondString are actually the same object - where as in thirdString you explicitly asked for a new object to be created on the heap.
I recommend reading the section about string literals in the spec.
It provides more information on how and when strings are pooled.
Also, take note to these bullets at the end of the section:
Literal strings within the same class (§8) in the same package (§7) represent references to the same String object (§4.3.1).
Literal strings within different classes in the same package represent references to the same String object.
Literal strings within different classes in different packages likewise represent references to the same String object.
Strings computed by constant expressions (§15.28) are computed at compile time and then treated as if they were literals.
Strings computed by concatenation at run time are newly created and therefore distinct.

For firstString and secondString, JVM will lookup the string pool and return the reference of "String".
For thirdString, JVM will not lookup the string pool and will only create a String object in heap.
For OneString.intern(), JVM will lookup the reference in string pool, add OneString to string pool if OneString does not exist in it, and return the reference.

thirdString is NOT from the pool. It is not a string literal, you dynamically created it with the new operator.
secondString on the other hand - is taken from the pool (you assign a string literal to it), so the same object is assigned to both firstString and secondString.

"firstString == thirdString" returns false.
The method intern "returns a canonical representation for the string object."
If you assign the interned string:
thirdString=thirdString.intern();
last "firstString == thirdString" returns true

Related

Substring in if statement [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
This code separates a string into tokens and stores them in an array of strings, and then compares a variable with the first home ... why isn't it working?
public static void main(String...aArguments) throws IOException {
String usuario = "Jorman";
String password = "14988611";
String strDatos = "Jorman 14988611";
StringTokenizer tokens = new StringTokenizer(strDatos, " ");
int nDatos = tokens.countTokens();
String[] datos = new String[nDatos];
int i = 0;
while (tokens.hasMoreTokens()) {
String str = tokens.nextToken();
datos[i] = str;
i++;
}
//System.out.println (usuario);
if ((datos[0] == usuario)) {
System.out.println("WORKING");
}
}
Use the string.equals(Object other) function to compare strings, not the == operator.
The function checks the actual contents of the string, the == operator checks whether the references to the objects are equal. Note that string constants are usually "interned" such that two constants with the same value can actually be compared with ==, but it's better not to rely on that.
if (usuario.equals(datos[0])) {
...
}
NB: the compare is done on 'usuario' because that's guaranteed non-null in your code, although you should still check that you've actually got some tokens in the datos array otherwise you'll get an array-out-of-bounds exception.
Meet Jorman
Jorman is a successful businessman and has 2 houses.
But others don't know that.
Is it the same Jorman?
When you ask neighbours from either Madison or Burke streets, this is the only thing they can say:
Using the residence alone, it's tough to confirm that it's the same Jorman. Since they're 2 different addresses, it's just natural to assume that those are 2 different persons.
That's how the operator == behaves. So it will say that datos[0]==usuario is false, because it only compares the addresses.
An Investigator to the Rescue
What if we sent an investigator? We know that it's the same Jorman, but we need to prove it. Our detective will look closely at all physical aspects. With thorough inquiry, the agent will be able to conclude whether it's the same person or not. Let's see it happen in Java terms.
Here's the source code of String's equals() method:
It compares the Strings character by character, in order to come to a conclusion that they are indeed equal.
That's how the String equals method behaves. So datos[0].equals(usuario) will return true, because it performs a logical comparison.
It's good to notice that in some cases use of "==" operator can lead to the expected result, because the way how java handles strings - string literals are interned (see String.intern()) during compilation - so when you write for example "hello world" in two classes and compare those strings with "==" you could get result: true, which is expected according to specification; when you compare same strings (if they have same value) when the first one is string literal (ie. defined through "i am string literal") and second is constructed during runtime ie. with "new" keyword like new String("i am string literal"), the == (equality) operator returns false, because both of them are different instances of the String class.
Only right way is using .equals() -> datos[0].equals(usuario). == says only if two objects are the same instance of object (ie. have same memory address)
Update: 01.04.2013 I updated this post due comments below which are somehow right. Originally I declared that interning (String.intern) is side effect of JVM optimization. Although it certainly save memory resources (which was what i meant by "optimization") it is mainly feature of language
The == operator checks if the two references point to the same object or not.
.equals() checks for the actual string content (value).
Note that the .equals() method belongs to class Object (super class of all classes). You need to override it as per you class requirement, but for String it is already implemented and it checks whether two strings have the same value or not.
Case1)
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s1; // true
s1.equals(s2); // true
Reason: String literals created without null are stored in the string pool in the permgen area of the heap. So both s1 and s2 point to the same object in the pool.
Case2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2; // false
s1.equals(s2); // true
Reason: If you create a String object using the `new` keyword a separate space is allocated to it on the heap.
equals() function is a method of Object class which should be overridden by programmer. String class overrides it to check if two strings are equal i.e. in content and not reference.
== operator checks if the references of both the objects are the same.
Consider the programs
String abc = "Awesome" ;
String xyz = abc;
if(abc == xyz)
System.out.println("Refers to same string");
Here the abc and xyz, both refer to same String "Awesome". Hence the expression (abc == xyz) is true.
String abc = "Hello World";
String xyz = "Hello World";
if(abc == xyz)
System.out.println("Refers to same string");
else
System.out.println("Refers to different strings");
if(abc.equals(xyz))
System.out.prinln("Contents of both strings are same");
else
System.out.prinln("Contents of strings are different");
Here abc and xyz are two different strings with the same content "Hello World". Hence here the expression (abc == xyz) is false where as (abc.equals(xyz)) is true.
Hope you understood the difference between == and <Object>.equals()
Thanks.
== tests for reference equality.
.equals() tests for value equality.
Consequently, if you actually want to test whether two strings have the same value you should use .equals() (except in a few situations where you can guarantee that two strings with the same value will be represented by the same object eg: String interning).
== is for testing whether two strings are the same Object.
// These two have the same value
new String("test").equals("test") ==> true
// ... but they are not the same object
new String("test") == "test" ==> false
// ... neither are these
new String("test") == new String("test") ==> false
// ... but these are because literals are interned by
// the compiler and thus refer to the same object
"test" == "test" ==> true
// concatenation of string literals happens at compile time resulting in same objects
"test" == "te" + "st" ==> true
// but .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) ==> false
It is important to note that == is much cheaper than equals() (a single pointer comparision instead of a loop), thus, in situations where it is applicable (i.e. you can guarantee that you are only dealing with interned strings) it can present an important performance improvement. However, these situations are rare.
Instead of
datos[0] == usuario
use
datos[0].equals(usuario)
== compares the reference of the variable where .equals() compares the values which is what you want.
Let's analyze the following Java, to understand the identity and equality of Strings:
public static void testEquality(){
String str1 = "Hello world.";
String str2 = "Hello world.";
if (str1 == str2)
System.out.print("str1 == str2\n");
else
System.out.print("str1 != str2\n");
if(str1.equals(str2))
System.out.print("str1 equals to str2\n");
else
System.out.print("str1 doesn't equal to str2\n");
String str3 = new String("Hello world.");
String str4 = new String("Hello world.");
if (str3 == str4)
System.out.print("str3 == str4\n");
else
System.out.print("str3 != str4\n");
if(str3.equals(str4))
System.out.print("str3 equals to str4\n");
else
System.out.print("str3 doesn't equal to str4\n");
}
When the first line of code String str1 = "Hello world." executes, a string \Hello world."
is created, and the variable str1 refers to it. Another string "Hello world." will not be created again when the next line of code executes because of optimization. The variable str2 also refers to the existing ""Hello world.".
The operator == checks identity of two objects (whether two variables refer to same object). Since str1 and str2 refer to same string in memory, they are identical to each other. The method equals checks equality of two objects (whether two objects have same content). Of course, the content of str1 and str2 are same.
When code String str3 = new String("Hello world.") executes, a new instance of string with content "Hello world." is created, and it is referred to by the variable str3. And then another instance of string with content "Hello world." is created again, and referred to by
str4. Since str3 and str4 refer to two different instances, they are not identical, but their
content are same.
Therefore, the output contains four lines:
Str1 == str2
Str1 equals str2
Str3! = str4
Str3 equals str4
You should use string equals to compare two strings for equality, not operator == which just compares the references.
It will also work if you call intern() on the string before inserting it into the array.
Interned strings are reference-equal (==) if and only if they are value-equal (equals().)
public static void main (String... aArguments) throws IOException {
String usuario = "Jorman";
String password = "14988611";
String strDatos="Jorman 14988611";
StringTokenizer tokens=new StringTokenizer(strDatos, " ");
int nDatos=tokens.countTokens();
String[] datos=new String[nDatos];
int i=0;
while(tokens.hasMoreTokens()) {
String str=tokens.nextToken();
datos[i]= str.intern();
i++;
}
//System.out.println (usuario);
if(datos[0]==usuario) {
System.out.println ("WORKING");
}
Generally .equals is used for Object comparison, where you want to verify if two Objects have an identical value.
== for reference comparison (are the two Objects the same Object on the heap) & to check if the Object is null. It is also used to compare the values of primitive types.
== operator compares the reference of an object in Java. You can use string's equals method .
String s = "Test";
if(s.equals("Test"))
{
System.out.println("Equal");
}
If you are going to compare any assigned value of the string i.e. primitive string, both "==" and .equals will work, but for the new string object you should use only .equals, and here "==" will not work.
Example:
String a = "name";
String b = "name";
if(a == b) and (a.equals(b)) will return true.
But
String a = new String("a");
In this case if(a == b) will return false
So it's better to use the .equals operator...
The == operator is a simple comparison of values.
For object references the (values) are the (references). So x == y returns true if x and y reference the same object.
I know this is an old question but here's how I look at it (I find very useful):
Technical explanations
In Java, all variables are either primitive types or references.
(If you need to know what a reference is: "Object variables" are just pointers to objects. So with Object something = ..., something is really an address in memory (a number).)
== compares the exact values. So it compares if the primitive values are the same, or if the references (addresses) are the same. That's why == often doesn't work on Strings; Strings are objects, and doing == on two string variables just compares if the address is same in memory, as others have pointed out. .equals() calls the comparison method of objects, which will compare the actual objects pointed by the references. In the case of Strings, it compares each character to see if they're equal.
The interesting part:
So why does == sometimes return true for Strings? Note that Strings are immutable. In your code, if you do
String foo = "hi";
String bar = "hi";
Since strings are immutable (when you call .trim() or something, it produces a new string, not modifying the original object pointed to in memory), you don't really need two different String("hi") objects. If the compiler is smart, the bytecode will read to only generate one String("hi") object. So if you do
if (foo == bar) ...
right after, they're pointing to the same object, and will return true. But you rarely intend this. Instead, you're asking for user input, which is creating new strings at different parts of memory, etc. etc.
Note: If you do something like baz = new String(bar) the compiler may still figure out they're the same thing. But the main point is when the compiler sees literal strings, it can easily optimize same strings.
I don't know how it works in runtime, but I assume the JVM doesn't keep a list of "live strings" and check if a same string exists. (eg if you read a line of input twice, and the user enters the same input twice, it won't check if the second input string is the same as the first, and point them to the same memory). It'd save a bit of heap memory, but it's so negligible the overhead isn't worth it. Again, the point is it's easy for the compiler to optimize literal strings.
There you have it... a gritty explanation for == vs. .equals() and why it seems random.
#Melkhiah66 You can use equals method instead of '==' method to check the equality.
If you use intern() then it checks whether the object is in pool if present then returns
equal else unequal. equals method internally uses hashcode and gets you the required result.
public class Demo
{
public static void main(String[] args)
{
String str1 = "Jorman 14988611";
String str2 = new StringBuffer("Jorman").append(" 14988611").toString();
String str3 = str2.intern();
System.out.println("str1 == str2 " + (str1 == str2)); //gives false
System.out.println("str1 == str3 " + (str1 == str3)); //gives true
System.out.println("str1 equals str2 " + (str1.equals(str2))); //gives true
System.out.println("str1 equals str3 " + (str1.equals(str3))); //gives true
}
}
The .equals() will check if the two strings have the same value and return the boolean value where as the == operator checks to see if the two strings are the same object.
Someone said on a post higher up that == is used for int and for checking nulls.
It may also be used to check for Boolean operations and char types.
Be very careful though and double check that you are using a char and not a String.
for example
String strType = "a";
char charType = 'a';
for strings you would then check
This would be correct
if(strType.equals("a")
do something
but
if(charType.equals('a')
do something else
would be incorrect, you would need to do the following
if(charType == 'a')
do something else
a==b
Compares references, not values. The use of == with object references is generally limited to the following:
Comparing to see if a reference is null.
Comparing two enum values. This works because there is only one object for each enum constant.
You want to know if two references are to the same object
"a".equals("b")
Compares values for equality. Because this method is defined in the Object class, from which all other classes are derived, it's automatically defined for every class. However, it doesn't perform an intelligent comparison for most classes unless the class overrides it. It has been defined in a meaningful way for most Java core classes. If it's not defined for a (user) class, it behaves the same as ==.
Use Split rather than tokenizer,it will surely provide u exact output
for E.g:
string name="Harry";
string salary="25000";
string namsal="Harry 25000";
string[] s=namsal.split(" ");
for(int i=0;i<s.length;i++)
{
System.out.println(s[i]);
}
if(s[0].equals("Harry"))
{
System.out.println("Task Complete");
}
After this I am sure you will get better results.....

Understanding how string comparison works in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I compare strings in Java?
I am new to Java and I have difficulties in understanding String comparison. Can anyone explain the differences between the following scenarios?
Scenario 1 :
String a = "abc";
String b = "abc";
When I run the if(a == b) it returns true.
Scenario 2 :
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
What is the difference?
== operator compares the references of two objects in memory. If they point to the same location then it returns true.String object in java are Immutable, so when you create Strings like in scenario1 then it didn't create new string. It just points the second string to the memory location of first string.
However, .equals() method compares the content of the String. When strings has same value then this method returns true.
So, in general it is recommended to use equals() method instead of ==.
It's because of Java String constant memory pool. Same valued literals are stored once.
String a = "abc";
String b = "abc";
// Now there is 1 string ("abc") and 2 references pointing to it.
String a = new String("abc");
String b = new String("abc");
// Now you have 2 string instances and 2 references.
Scenario 1 returns true because of a compiler optimization.
In general you should use equals() instead of == to compare strings.
In Java you need to use like this if(str.equals(str2)) which compares actual value of string rather than references.
Case1:
String a = "abc";
String b = "abc";
if(a == b)
In this case abc is cached in String constant pool thus a new string is not created String b = "abc"; b just refers to the string created by a it returns true as a and b both point to the same Object in the memory.
Case2:
String a = new String("abc");
String b = new String("abc");
and run if(a == b) then it returns false.
Here a two Strings are created and == operator just checks if two references point to the same reference, which it doesnt in this case thus it returns false
Two ways of creating string are
1) String s ="hello"; No. of string literal = 1 i.e. "hello" - No. of String objects on heap = 0
2) String s= new String("hello"); - No. of string literals =1 and No. of string objects =1
Java maintains a string pool of "LITERALS" and objects are going to stay on heap.
Advantage of string pooling: 1) Reduced memory usage*(PermGenSpace Issue) 2) Faster Comparision i.e == comparision 3) Faster lookup
Disadvantages: 1) Overhead of maintaining pool
How to pool String objects? Use Intern() on a string to add it to the pool. Downside of interning: 1) You may forget to intern some strings and compare them by == leading to unexpected results.
The reason is that the String literal "abc" will be turned into a global String instance for all its ocurrences, it will be the same String instance therefore you can be sure that "abc" == "abc". It is possible for the compiler to do that because String instances are immutable. However, if you explicitly allocate the String they will be two different instances and they will also be different to the String instance implicitly created by the compiler i.e. new String("abc") != new String("abc") and "abc" != new String("abc").
Another good example to understand what the compiler is doing is to look at this code:
"abc".contains("a");
you see that the literal behaves like an instance of a String type. You may exploit this to minimize programming errors e.g.
// this is OK and the condition will evaluate to false
String myStringValue = null;
if ("abc".equals(myStringValue)) { // false
whereas this code results in NPE:
// this will produce a NPE
String myStringValue = null;
if (myStringValue.equals("abc")) { // NPE

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.

Java:literal strings

class A {
String s4 = "abc";
static public void main(String[]args ) {
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
A o = new A();
String s5 = new String("def");
System.out.println("s1==s2 : " + (s1==s2));
System.out.println("s1==s1.intern : " + (s1==s1.intern()));
System.out.println("s1==s3 : " + (s1==s3));
System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern()));
System.out.println("s1==s4 : " + (s1==o.s4));
}
}
The output:
s1==s2 : true
s1==s1.intern : true
s1==s3 : false
s1.intern==s3.intern : true
s1==s4 : true
My questions:
1.What happens for "String s1 = "abc"? I guess the String object is added to the pool in class String as an interned string? Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?
2.What happens for "String s2 = "abc"? I guess no any object is created.But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?
3.Seems String s3 = new String("abc") does not use interned string.Why?
4.Will String s5 = new String("def") create any new interned string?
The compiler creates a String object for "abc" in the constant pool, and generates a reference to it in the bytecode for the assignment statement.
See (1). No searching; no performance issue.
This creates a new String object at runtime, because that is what the 'new' operator does: create new objects.
Yes, for "def", but because of (3) a new String is also created at runtime.
The String objects at 3-4 are not interned.
1.What happens for "String s1 = "abc"?
At compile time a representation of the literal is written to the "constant pool" part of the classfile for the class that contains this code.
When the class is loaded, the representation of the string literal in the classfile's constant pool is read, and a new String object is created from it. This string is then interned, and the reference to the interned string is then "embedded" in the code.
At runtime, the reference to the previously created / interned String is assigned to s1. (No string creation or interning happens when this statement is executed.)
I guess the String object is added to the pool in class String as an interned string?
Yes. But not when the code is executed.
Where is it placed on? The "permanent generation" or just the heap(as the data member of the String Class instance)?
It is stored in the permgen region of the heap. (The String class has no static fields. The JVM's string pool is implemented in native code.)
2.What happens for "String s2 = "abc"?
Nothing happens at load time. When the compiler created the classfile, it reused the same constant pool entry for the literal that was used for the first use of the literal. So the String reference uses by this statement is the same one as is used by the previous statement.
I guess no any object is created.
Correct.
But does this mean that the Java Intepreter needs to search all the interned strings? will this cause any performance issue?
No, and No. The Java interpretter (or JIT compiled code) uses the same reference as was created / embedded for the previous statement.
3.Seems String s3 = new String("abc") does not use interned string.Why?
It is more complicated than that. The constructor call uses the interned string, and then creates a new String, and copies the characters of the interned string to the new String's representation. The newly created string is assigned to s3.
Why? Because new is specified as always creating a new object (see JLS), and the String constructor is specified as copying the characters.
4.Will String s5 = new String("def") create any new interned string?
A new interned string is created at load time (for "def"), and then a new String object is created at runtime which is a copy of the interned string. (See previous text for more details.)
See this answer on SO. Also see this wikipedia article on String Interning.
String s1 = "abc"; creates a new String and interns it.
String s2 = "abc"; will drag the same Object used for s1 from the intern pool. The JVM does this to increase performance. It is quicker than creating a new String.
Calling new String() is redundant as it will return a new implicit String Object. Not retrieve it from the intern pool.
As Keyser says, == compares the Strings for Object equality, returning true if they are the same Object. When comparing String content you should use .equals()

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