How and what does "==" operator in java check? - java

I have been stuck with this for a while now, Actually I have 2 objects which according to me are same, I have overriden the hashCode method to create equal hash codes for both, still when I compare them for equality using "==" or Object's equals(which too uses "=="), it returns false to me, The below scenario should exactly explain:::
1)HashCode-->-626561382 AND 2)HashCode--->-626561382
1)IdentityHashCode-->19640463
2)IdentityHashCode-->22330755
1)Bean1=beans.OrdersBean#daa76e9a AND 2)Bean2=beans.OrdersBean#daa76e9a
Check MySelf for(==)-->false
Check Object's Equals()-->false
Please kindly explain me why is this happening????

== operator compare refrences(Memory location) of Objects in java...
if you compare objects then use .equals()
if(obj1.equals(obj2)){
}
See here

To compare two objects for equal value you need to override the equals method.
The == operator as others have mentioned compares references (i.e. is it the exact same object)
Explanation
If you take the example of identical twins Ben and Adam, using an == would return false when comparing the two since Ben is not Adam (even though they look the same), if you use .equals and the comparison is based on looks then this would return true.

In Java == is used to compare reference. To valuate if two objects are equivalent use equals.
Note If you have to compare custom objects consider ovverriding equals in your class according to your equivalence criteria.

Override .equals from the parent Object's method, this is intended for "deeper" comparisons whereas == pertains to checking that the references (identifiers) are referring to (so that updates to one apply to both) the same instantiation.

1. Using '==' :
When you want to check if two reference variables are referring to a same object you should use == operator in java. For example - (Assume there is a class called Person)
Person person1 = new Person();
Person person2 = person1;
System.out.println(person1 == person2); // true
Here as we have used new only once, only one object is getting created in the heap memory and we are assigning it to a reference variable -> person1. In the second statement we are assigning person1 to person2. So actually there is only one object in memory but both person1 and person2 are referring to the same object.
[In short we can say that, similar to primitives, == compares the value in the variable which in case of reference variables is memory address of the actual object].
2. Using '.equals()' :
When you want to check if the two objects are meaningfully equal then use .equals() method. For example -
Person person1 = new Person();
Person person2 = new Person();
System.out.println(person1.equals(person2)); // false
Here we are creating altogether two different objects, so they are not meaningfully equal. Hence the equals() method will return false.

Related

String interning and HashSet in java

I have read about string interning, in which String literals are reused, whereas String object created using new aren't reused. This can be seen below when I print true and false for their equality. To be specific, (p1==p2)!=p3, So there are two objects, one pointed by p1 and p2 and another by p3. However, when I add them to HashSet, all considered same. I was expecting a.size() to return 2, but it returned 1. Why is this so?
package collections;
import java.util.HashSet;
public class Col {
public static void main(String[] args) {
method1();
}
public static void method1()
{
HashSet a = new HashSet();
String p1 = "Person1";
String p2 = "Person1";
String p3 = new String("Person1");
if(p1 == p2)
System.out.println(true);
else
System.out.println(false);
if(p1 == p3)
System.out.println(true);
else
System.out.println(false);
a.add(p1);
a.add(p2);
a.add(p3);
System.out.println(a.size());
}
}
Output
true
false
1
HashSet uses equality to keep a unique set of values, not identity (i.e., if two objects are equals to each other, but not ==, a HashSet will only keep one of them).
You can implement a set that uses identity instead of equality by using the JDK's IdentityHashMap with a dummy value shared between all keys, in a similar way that HashSet is based on HashMap.
I have read about string interning, in which String literals are reused, whereas String object created using new aren't reused. This can be seen below when I print true and false for their equality. To be specific, (p1==p2)!=p3, So there are two objects, one pointed by p1 and p2 and another by p3. However, when I add them to HashSet, all considered same. I was expecting a.size() to return 2, but it returned 1.
This is right only if you compare String using ==, the result is different when comparing using equals() method. (In doubt, you can test).
When adding into HashSet, the comparison method used is equals() as its proper for objects. And so, p1, p2 and p3 are equals.
You can try testing using equals() it will output true, true, 1 instead of true, false, 1
p1 and p2 are string literals and they are pointing to the same value because of string pool. So, when we are comparing them using == then they are matching.
p3 is a string object, so when we match using == then it tries to match using reference, so it gives false.
HashSet's add method call HashMap's put method internally. HashMap's put method use hashCode and equals method to set the value in HashMap. String implement hashCode and equals method and provide same hashCode for same value. HashSet contain unique value, so it store only one value.
This is one of those cases where I would recommend learning how to use javap to understand how your code is compiled but let me try to explain what is going on under the hood.
When Java compiles that class, it creates instructions for building what is called the constant pool for that class. That constant pool will hold a reference to a string with the value "Person1". The compiled logic will also say p1 and p2's value should be set to the constant pool's reference to that string (the address in memory that it lives in). Calling p1==p2 will return true because they literally have the same exact value. When you call String p3 = new String("Person1"); you are telling Java to create a new string in a different place in memory which is merely a copy of the original one and then set p3's value as a reference to the place in memory that the new string object lives in. So if you call p1 == p3 it will return false because what you are saying is "does p1's location in memory equals p2's location in memory?"
As others have pointed out, if you called p1.equals(p3) it returns true because .equals compares the string values instead of the references. And a HashSet will see them all the same because it uses the method .hashCode which is similar to .equals in the sense that it generates a hash off of the string value.
Hopefully that clears up some of the confusion!

What is the difference between being shallowly and deeply equal? How is this applied to caching?

Found the following in my notes, but I am unable to make sense of it:
Primitive type wrapper classes implement caching for a limited number
of values.
This guarantees that a limited number of deeply equal wrapper objects are
also shallowly equal:
If o1.equals( o2 ) then o1 == o2.
For example, new Integer( 0 ) == new Integer( 0 ).
In general this does not always work.
For example, new Integer( 666 ) == new Integer( 666 )
may not hold.
The reason for caching is that it saves memory.
In general caching works for “small” primitive values.
I don't understand what is meant by this, or what the difference is between a deep (.equals()) and shallow(==) equals. I know in practice, .equals must be used to objects and == for Integral values, but the actual reasoning for this alludes me.
I assume by the names that shallow maybe just checks that both the values are of the same type and name, which deep checks that both variables point to the same object? I don't see how the caching would come into play here though, or why it would be useful.
When you do == you are comparing the references for equality. This means you're saying "is the address in memory the same for both Objects?"
When you do .equals() you are comparing the Objects themselves for equality. This means you're saying "do these two Objects consider themselves equal?"
The example that was given was poor. The only caching done for these numbers that's mandated by the JLS is the .valueOf() method. The constructor is not cached.
Furthermore, the JLS only specifies the minimum you must cache [-128:127]. JVM implementations may cache more if they so choose. This means Integer.valueOf(500) == Integer.valueOf(500) may be false on some machines, but true on others.
class biziclop {
public static void main(String[] args) {
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(500) == new Integer(500));
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
}
}
Results in:
C:\Documents and Settings\glow\My Documents>java biziclop
false
false
true
false
C:\Documents and Settings\glow\My Documents>
See a more detailed answer here (the comments are a gem!): Why do people still use primitive types in Java?
Well, actually shallow/deep dissection is different from ==/equal dissection:
== compares for object identity, that is you checking whether
operands are the same in fact
(two references to the same area of memory),
whereas equals compares for object
equivalence, that is "logical" value
of two, possibly not identical
objects, is the same. If for two
objects
a == b
then it's true that
a.equals(b) // if a != null
, but opposite isn't true in all
cases.
shallow/deep distinction makes sense
only for equals comparison.
Shallow means that you compare only
immediate contents of two objects to
find whether they "equal" in your
sense, whereas deep means that you
compare contents of your objects
recursively until all you need to
compare is primitive fields. If
you define equals method of your
objects as sequence of calls to
equals on instance fields of these
objects, you use deep comparison. If
you define equals using ==
operator to compare compound types,
such as Strings, then you use shallow comparison -- and that's incorrect in Java.
Morale of all of this is that you must never use == to compare two compound objects, unless you consider them equal only if they are the same.
What you call "shallow equal" is identity: two references (i.e. objects) are identical if they are the very same instances. If you know what pointers are in other languages, you can compare identity to pointer equality.
What you call "deep equal" is equality: two objects a and b are equal if a.equals(b) returns true (and hopefully vice versa). The correctness of equality strongly depends on the way the equals method is implemented. See the Javadoc of the Object class for more details.
First off: new Integer(0) == new Integer(0) will never evaluate to true, as new always creates a new object, sidestepping any autoboxing-caching mechanism that might exist.
What you probably heard about was autoboxing (i.e. automatic conversion of primitive values to their respective wrapper classes when necessary). Autoboxing uses a mechanism that's also accessible using the wrapper classes valueOf() methods. In other words: auto-boxing an int to an Integer works pretty much the same as calling Integer.valueOf(int).
Integer.valueOf(0) == Integer.valueOf(0) will evaluate to true, because common values (i.e. values with a low absolute value) are cached. You'll get the same Integer object when you call valueOf(0) twice in a row. This is not necessarily true with higher values (such as 666 in your example).
equals() tests whether two objects are essentially the same, but it can return true for two distinct objects; i.e., two different paper clips are "equals". "==" for reference types tests whether two references refer to the same object -- i.e., a paper clip is == only to itself. == tests identity, which equals tests equivalence.
You could have two distinct Integer objects with a 0 in them (they are equals()); caching means saving objects and reusing them when possible.

Example of ==, equals and hashcode in java

Given this:
String s1= new String("abc");
String s2= new String("abc");
String s3 ="abc";
System.out.println(s1==s3);
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
System.out.println(s3.hashCode());
Output is:
false
false
true
true
96354
96354
96354
Here == is giving false for each object but the hashcode for each String object is same. Why is it so?
== does compare real equality of objects (I mean - both references point to the same object), not their content, whereas .equal compares content (at least for String).
String a = new String("aa");
String b = new String("aa");
a and b are pointing to different objects.
Notice also that if objects are equal then their hashchodes must be the same, but if hashcodes are the same, it doesn't mean that objects are equal.
The equals contract says that if o1.equals(o2), then o1.hashCode() == o2.hashCode(). It doesn't specify anything about the hash codes of unequal objects. You could have a method like
public int hashCode()
{
return 42;
}
and it'd fulfill the contract. It's just expected that the hash code be related to the value of the object, in order to make hash tables work more efficiently.
Now, as for why your == doesn't work, two objects will always be compared by reference. That is, if o1 == o2, then o1 and o2 are the exact same object. That's rarely what you want; you usually want to see if o1.equals(o2) instead.
When you use ==, you are comparing if two variables hold reference to the same Object. In other words s1 == s2 is like asking: are the s1 and s2 variables referring to the same String object? And that's not true, even when both String objects have the same "abc" value.
When you use equals(), you are comparing the value of both objects. Both objects may not be the same, but their value (in this case "abc") is the same, so it returns true.
How do you define whether an object is equal to another? That's up to you. In this case the String object already defines this for you, but for example if you define a Person object, how do you know if a person P1 is equal to P2? You do that by overriding equals() and hashCode().
== tells you whether the two variable references point at the same object in memory, nothing more. equals() and hashCode() both look at the contents of the object and each uses its own algorithm for calculation.

Java equals and hashmaps problem

So I'm learning Java and I'm trying to understand equals, but I really don't understand it. So my question is: how does equals works?
Thanks
equals is a method you use to discover if two given objects are the same. The default implementation of equals for an object is: They are the same if they have the exact same reference.
Sometimes, you don't want this. Say you have a ComplexNumber class, and two instances with value 1+i. You don't want them not to be equal just because they are different instances. In essence, they represent the same number. In this case, you should override equals to make sure it behaves as intended.
HashMaps use info from equals to know if the key you passed is already there.
From Effective Java book:
Always override hashcode when you
override equals
I'd also add to that: specially if you're using a Hashmap =)
Hashmaps uses also hashcode() to search faster for the keys, and the result for hashcode() must be consistent with the equals result. In other words, if x.equals(y), then x.hashcode() == y.hashcode() (or you may have undefined behavior for your hashmap). You may have x and y with x.hashcode() == y.hashcode() and !x.equals(y)
If you want a more specific answer, please make a more specific question =).
The equals method will compare values for equality.
the method equals is defined in the object class so which means that every other class can use this method to compare how it works: it will first check if its referring to its self then the haschode's of the object and if those are equal if so, it will then check each field in that object against the fields of the object you are comaparing to why you might ask co's the haschode could be the same but it can still contain other value's in the fields the odds are low but its needed to compare more in depth then.
equals() means "meaningfully equivalent." It's not the same as ==, which means "these are the same object." All classes have the equals() method, inheirited from the Object class. For example, say you write a Car class that stores make, model and owner:
Car carOne = new Car("Buick", "LeSabre", "John Doe");
Car carTwo = carOne;
Here, equals() and == will both return true, because both references point to the same car. But, for
Car carOne = new Car("Buick", "LeSabre", "John Doe");
Car carTwo = new Car("Buick", "LeSabre", "John Doe");
there are two distinct objects, so == returns false. However, since both cars are Buick LeSabres owned by John Doe, your equals() should be written return true (assuming for this example that nobody owns more than one car of the same type).
Also, as Samuel pointed out, if you override equals(), you should also override hashCode(); the reasons for that are outside the scope of this question, and well-documented elsewhere.

Is Java's assertEquals method reliable?

I know that == has some issues when comparing two Strings. It seems that String.equals() is a better approach. Well, I'm doing JUnit testing and my inclination is to use assertEquals(str1, str2). Is this a reliable way to assert two Strings contain the same content? I would use assertTrue(str1.equals(str2)), but then you don't get the benefit of seeing what the expected and actual values are on failure.
On a related note, does anyone have a link to a page or thread that plainly explains the problems with str1 == str2?
You should always use .equals() when comparing Strings in Java.
JUnit calls the .equals() method to determine equality in the method assertEquals(Object o1, Object o2).
So, you are definitely safe using assertEquals(string1, string2). (Because Strings are Objects)
Here is a link to a great Stackoverflow question regarding some of the differences between == and .equals().
assertEquals uses the equals method for comparison. There is a different assert, assertSame, which uses the == operator.
To understand why == shouldn't be used with strings you need to understand what == does: it does an identity check. That is, a == b checks to see if a and b refer to the same object. It is built into the language, and its behavior cannot be changed by different classes. The equals method, on the other hand, can be overridden by classes. While its default behavior (in the Object class) is to do an identity check using the == operator, many classes, including String, override it to instead do an "equivalence" check. In the case of String, instead of checking if a and b refer to the same object, a.equals(b) checks to see if the objects they refer to are both strings that contain exactly the same characters.
Analogy time: imagine that each String object is a piece of paper with something written on it. Let's say I have two pieces of paper with "Foo" written on them, and another with "Bar" written on it. If I take the first two pieces of paper and use == to compare them it will return false because it's essentially asking "are these the same piece of paper?". It doesn't need to even look at what's written on the paper. The fact that I'm giving it two pieces of paper (rather than the same one twice) means it will return false. If I use equals, however, the equals method will read the two pieces of paper and see that they say the same thing ("Foo"), and so it'll return true.
The bit that gets confusing with Strings is that the Java has a concept of "interning" Strings, and this is (effectively) automatically performed on any string literals in your code. This means that if you have two equivalent string literals in your code (even if they're in different classes) they'll actually both refer to the same String object. This makes the == operator return true more often than one might expect.
In a nutshell - you can have two String objects that contain the same characters but are different objects (in different memory locations). The == operator checks to see that two references are pointing to the same object (memory location), but the equals() method checks if the characters are the same.
Usually you are interested in checking if two Strings contain the same characters, not whether they point to the same memory location.
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
The JUnit assertEquals(obj1, obj2) does indeed call obj1.equals(obj2).
There's also assertSame(obj1, obj2) which does obj1 == obj2 (i.e., verifies that obj1 and obj2 are referencing the same instance), which is what you're trying to avoid.
So you're fine.
Yes, it is used all the time for testing. It is very likely that the testing framework uses .equals() for comparisons such as these.
Below is a link explaining the "string equality mistake". Essentially, strings in Java are objects, and when you compare object equality, typically they are compared based on memory address, and not by content. Because of this, two strings won't occupy the same address, even if their content is identical, so they won't match correctly, even though they look the same when printed.
http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/
"The == operator checks to see if two Objects are exactly the same Object."
http://leepoint.net/notes-java/data/strings/12stringcomparison.html
String is an Object in java, so it falls into that category of comparison rules.

Categories