This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
Actually am testing the functionality of Scanner.
I have a very simple program which has a String variable which contains "abc".Then am reading other String(value "abc") from Scanner using next() method(even i tried with nextLine()).
Then am comparing using the ==, to check whether they are equal according to ==(i know i can compare with equals method which is working as excepted), the strange thing is that it is returning false when i compare using == , even though their hashcode() s are equal and equals() method returning true..
import java.util.Scanner;
public class Tester1234 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String str1="abc";
System.out.println("Eneter abc");
String str2=scanner.next();
System.out.println("str1.hascode()"+str1.hashCode()+"\tstr2.hascode()"+str2.hashCode()+"\tstr2.equals(str1)"+str1.equals(str2));
if(str1==str2)
{
System.out.println("equal");
}
else
{
System.out.println("not equal");
}
}
}
I want to know why it is behaving like this ??
Thanks...!
You are wrong as for the statement that
i know Strings with same content will point to same object in StringPool...
It is true as for literals whitch are hardcoded strings in the code. Compiler creates string pool on compile time and use existing references. But if you are building string on runtime using StringBuilder/StringBuffer (what i belive the Scanner does internally) you are NOT USING entities in string pool, thats why you will get two different objects (references) for the same string content. Workaround for such behaviour is to use intern() however it is performance hit, as interned strings are goint into permgen, and will not be garbage collected.
If we create an String like this...
String str1 = "abc";
object str1 created in String-Pool, and if we create
String str2 = new String("abc");
then, it created in heap, means another new Object.
this is the reason that your condition if(str1==str2) returns false, because these both are different objects.
But there hashcode is equal because both are "abc", so equals method returns true.
you are right that hashcode and equals returning true, hence it will return true for str2.equals(str1).
But str2 is new String and hence it is having difference memory address thats why it will not work for str2==str1. here you are comparing memory address and not content of the string.
Related
This question already has answers here:
String.equals versus == [duplicate]
(20 answers)
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
In Program 1 I have declared two String and initialized them as "MADAM". When running I am checking the equality of their reference variable (by '==' operator') then I am getting a "true" response.
But in Program 2 I am declaring a String 'S' and initialize it as "MADAM". After that i am running a reverse loop and storing the characters of 'S' in reverse order in other String variable. Now i have again tried to check the equality of reference variable (by '==' operator') and am getting the response as 'false'. As both the String objects are of same value and are stored in constant Pool Area so both the variable should equate and the output in both the scenario should be 'true'. But WHY it is not same?
Program 1:
class Reverse {
public static void main(String[] args) {
String s="MADAM"; String rev="MADAM"; System.out.println(s==rev);
}
}
Output - true
Program 2:
class Reverse {
public static void main(String[] args) {
String s="MADAM"; String rev="";
for(int x=s.length()-1;x>=0;x--) { rev+=s.charAt(x); }
System.out.println(s==rev);
}
}
Output- false
In program 1 java compiler saves "MADAM" string in one memory location and assigns both "s" and "rev" to that location hence "s==rev" returns true because they both refer to the same address.
you should use "equals()" method to compare two strings. e.equals(rev);
have a look at this question:
Java String.equals versus ==
In your first class both strings are initialize to same object. So both are pointing to same memory location.
Next class, Rev is intilialized to "" value and see to madam so both have got different memory location. So false.
In essence,
if you use == for comparison, you are comparing their identity.
If you want to compare the object's value, use .equals()
String s="MADAM"; String rev="MADAM"; System.out.println(s==rev);
The above code will return true, because both Strings will be stored in the same memory location.
However, you can try the following, it will return you false:
String s1 = "aaa";
String s2 = new String("aaa");
System.out.println(s1 == s2); //false (comparing memory location)
System.out.println(s1.equals(s2)); //true (comparing value)
Side note: It is generally a bad practice to create Strings using new String(""). It was only used for demonstration purposes only.
This question already has answers here:
Java: Why can String equality be proven with ==?
(3 answers)
Closed 8 years ago.
class test {
public static void main(String[] args) {
String a = "Hiabc";
String b = "abc";
String c = "abc";
System.out.println(a.substring(2,5)==b);
System.out.println(b==c);
}
}
output:
false
true
As far as I understand, Java's == look for addresses of the two compared objects. Yet, I don't understand why b==c is true because they must have different addresses. Also, if b==c, then why is a.substring(2,5), which is "abc" == b false?
As far as I understand, Java's == look for addresses of the two compared objects.
Almost correct. Java uses references not addresses, e.g. a reference is strongly typed: See https://softwareengineering.stackexchange.com/questions/141834/how-is-a-java-reference-different-from-a-c-pointer
why b==c is true
The variable b and c are initialized with the same string reference, because they reference the same string literal "abc".
why doesn't substring expression reference the string literal "abc"?
Because the javadoc of substring() says
Returns a new string that is a substring of this string.
So the method does not ensure that a reference to a string from the constant pool is returned. If you want this you have to do
a.substring(2,5).intern()
and than
a.substring(2,5).intern()==b
will be true.
Never compare strings with == in Java.
Use .equal or .equalIgnoreCase methods instead.
The difference between a.substring(2,5) and b is because substring created another String object and it's on a different location than b. It's not about the characters ...
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I don't know what's going on with it. Code below. I'm not trying to get anyone to code the whole thing for me, just don't know what's wrong and would like a little help
private void javabutton1(java.awt.event.ActionEvent evt) {
String testa= new String (jPasswordField2.getPassword());
String testb= new String (jPasswordField3.getPassword());
if (testa.toString() == testb.toString()){
JOptionPane.showMessageDialog(this, "Success");
}
}
When I replace testa.toString() == testb.toString()) with "A" == "A".
The messagebox "Success" is achieved but this entry comparison won't work
Also: The text entered in both jPasswordField2 and jPasswordField3 are the same.
You should try:
testa.equals(testb)
And there is no point of doing this:
String testa = getSomething();
String temp = testa.toString();
// becasue
testa.equals(temp) // always true
If you would have something like:
String a = getSomething();
String b = a;
a == b // now this is true, because they have the same reference/pointer
Use .equals() when comparing strings.
Try with String.equals()
Consider two different reference variables str1 and str2
str1 = new String("abc");
str2 = new String("abc");
if you use the equals()
System.out.println((str1.equals(str2))?"TRUE":"FALSE");
You will get the output as TRUE
if you use ==
System.out.println((str1==str2)?"TRUE":"FALSE");
Now you will get the FALSE as output because both str1 and str2 are pointing to two different objects even though both of them share the same string content. It is because of new String() everytime a new object is created.
Fix your issue by using String.equals(string) like this
String testa= new String (jPasswordField2.getPassword());
String testb= new String (jPasswordField3.getPassword());
if (testa.equals(testb)){
JOptionPane.showMessageDialog(this, "Success");
}
Basically, you should never use == to compare Strings, instead use equals(), so for you:
testa.equals(testb)
The difference is that == is used to compare references, it is saying: "Do these two String references point to the same String object in memory?"...this is unpredictable due to how Java stores Strings, which basically accounts for why "A" == "A" returns true...not something to go into here.
The equals() method is more what you would expect, in the Java Class String, this method basically checks whether or not each character in the String is the same, and returns true if they do.
If it's an object, you should use equals() to compare, if its a primitive data type, such as an int (or you are checking if a reference is null) then use ==.
While I agree with Takendarkk that answer duplicate questions promotes their repeated posting, I think there is at least one issue that should be noted which has not been mentioned. StephenTG asked a poignant question in the comments: "Why do you need to convert your Strings to Strings?"
Given the name of your variables, if you are indeed using the swing JPasswordField, then the getPassword() method returns a char[] array. You don't need to convert this to a string, you can compare them using java.utils.Arrays#equals(char[]. char[]) to get the result you desire. Your code might look like this:
private void javabutton1(java.awt.event.ActionEvent evt) {
char[] testa = jPasswordField2.getPassword();
char[] testb = jPasswordField3.getPassword();
if (Arrays.equals(testa, testb)){
JOptionPane.showMessageDialog(this, "Success");
}
}
I have written the code to check whether the given string is palindrome or not. But here I didn't create any String object explicitly. When we don't create explicitly, "==" also should work to compare the strings. But here I am not getting correct output if I use ==. For the clarity in my question, I have given another code also below
Code 1:Here. "==" is not working.
class Palindrome
{
public static void main(String[] args)
{
StringBuffer sb1=new StringBuffer();
sb1.append("anna");
String s1=sb1.toString();
StringBuffer sb2=new StringBuffer();
sb2=sb1.reverse();
String s2=sb2.toString();
if(s1.equals(s2))
{
System.out.println("The given String is a Palindrome");
}
else
System.out.println("Not a Palindrome");
}
}
Code 2: Here == works
class Stringdemo
{
public static void main(String[] args)
{
String str1="hello";
String str2="hello";
if(str1==str2)
{
System.out.println("both strings are same");
}
else
{
System.out.println("both strings are not Same");
}
}
}
Using StringBuilder/Buffer.toString() will create a new instance hence why equals() works, but == doesn't. In the case of using string literals, any string that is a string literal will be added to the constants pool of the class, and hence string1 and string2 will merely point to that same reference within the constant pool for "hello", ergo == says true because they are the same reference.
"==" compares object reference values where "equals()" compares object contents. "==" is only really useful for comparing primitives.
When you call "sb2.toString()" it creates a new object which has a new reference value.
sb2.toString(); creates a new String. == won't work here
it will however work if you use sb2.toString().intern() instead
== checks for object identity equality (i.e., same memory address).
.equals() checks for for equality of the value.
When you create a new string literal:
String str1="hello";
String str2="hello";
Java calls the String.intern() method to intern the new String, but will first check to see if that same String value already exists, and if it does it will return that (i.e., will not create a new instance). See the Javadoc comments on String.intern() for more details:
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.
This is why the second example works, but the StringBuilder example does not since calling sb2.toString creates a new instance, bypassing intern().
To be safe, you are better off using .equals() for any non-primative objects.
== operator just checks the object's reference, while equals() compares the strings for its characters seperately.
Since String are immutable objects therefore it shares the reference of objects if it is created already in memory.
Therefore,
String str1 = "hello"; //and
String str2 = "hello"; //are equal
Because both str1 and str2 shares the same reference of "hello".
As it is stated the == operator compares object references to check if they are referring to the same object on a heap. If so why am I getting the "Equal" for this piece of code?
public class Salmon {
public static void main(String[] args) {
String str1 = "Str1";
String str2 = "Str1";
if (str1 == str2) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
}
}
The program will print Equal. (At least using the Sun Hotspot and suns Javac.) Here it is demonstrated on http://ideone.com/8UrRrk
This is due to the fact that string-literal constants are stored in a string pool and string references may be reused.
Further reading:
What is String literal pool?
String interning
This however:
public class Salmon {
public static void main(String[] args) {
String str1 = "Str1";
String str2 = new String("Str1");
if (str1 == str2) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
}
}
Will print Not equal since new is guaranteed to introduce a fresh reference.
So, rule of thumb: Always compare strings using the equals method.
Java stores all Strings in a string table internally during a run. The references to the two strings are identical because in memory they're stored in the same place. Hence, Equal.
Your statement is right, that == compares object references. Try the same thing with any other class but Strings and you won't get the same result.
This code won't print Equal.
But if the two strings were the same, this case would be special.
Now that you've updated your code, it is the case :
A simple (but not totally exact) explanation is that the compiler see that the two strings are the same and do something like :
String str1 = "Str1";
String str2 = str1;
What really happens here is that the compiler will see the literal string and put it in the "String literal pool".
As a String can't be modified (it's immutable) the literal values of Strings (those found during compilation) are put in a "pool".
This way, if two different literal strings which have the same content (like in this particular case), the memory isn't wasted to store "Str1" and "Str1" two times.
People, you are forgetting that the process of placing literal strings in the pool is called "interning". The class String has a method called intern(). This method puts any string into the pool, even if it is not in the pool initially (not literal). This means that code like this:
String a = "hello";
String b = new String("hello");
b = b.intern();
System.out.println(a == b);
will print "true".
Now, why would someone need this? As you can imagine, string comparison a.equals(b) might take a long time if strings are the same length but different close to the end.
(Just look at the .equals() source code.).
However, comparing references directly is the same as comparing integers (pointers in C speak), which is near instant.
So, what does this give you? Speed. If you have to compare the same strings many, many times, your program performance will benefit tremendously if you intern these strings. If however you are going to compare strings only once, there will be no performance gain as the interning process itself uses equals().
I hope this explains this.
thanks
Comments above have summed it up pretty well.
I don't have a Java environment handy, but attempting the following should clarify things for you (hopefully this works as I anticipate).
String str1 = "Str1";
String str2 = "Str"; str2 += "1";
Should now print Not equal