What is the difference between identity and equality in OOP (Object Oriented Programming)?
identity: a variable holds the
same instance as another variable.
equality: two distinct objects can
be used interchangeably. they often
have the same id.
Identity
For example:
Integer a = new Integer(1);
Integer b = a;
a is identical to b.
In Java, identity is tested with ==. For example, if( a == b ).
Equality
Integer c = new Integer(1);
Integer d = new Integer(1);
c is equal but not identical to d.
Of course, two identical variables are always equal.
In Java, equality is defined by the equals method. Keep in mind, if you implement equals you must also implement hashCode.
Identity determines whether two objects share the same memory address. Equality determines if two object contain the same state.
If two object are identical then they are also equal but just because two objects are equal dies not mean that they share the same memory address.
There is a special case for Strings but that is off topic and you'll need to ask someone else about how that works exactly ;-)
Identity means it is the same object instance while equality means the objects you compare are to different instances of an object but happen to contain the same data.
Illustration (in java)
Date a = new Date(123);
Date b = new Date(123);
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
So a and b are different instances (different allocations in memory) but on the "data" level they are equal.
For instance,
In StackOverFlow:
identity: I am Michael, you are
sevugarajan, so we are not same.
equality: if we have same reputation
scores, we are equal in some ways.
In Java and similar languages which 'leak' the abstraction of a reference of an object, you can test whether two references refer to the same object. If they refer to the same object, then the references are identical. In Java, this is the == operator.
There is also an equals method which is used to test whether two objects have the same value, for example when used as keys of a HashSet (the hash code of equal objects should also be equal). Equal objects should have the same 'value' and semantics when used by client code.
Purer object-oriented languages do not have an identity comparison, as client code generally shouldn't care whether or not two objects have the same memory address. If objects represent the same real-world entity, then that is better modelled using some ID or key value rather than identity, which then becomes part of the equals contract. Not relying on the memory address of the object to represent real-world identity simplifies caching and distributed behaviour, and suppressing == would remove a host of bugs in string comparison or some uses of boxing of primitives in Java.
Think about the words "identical" and "equivalent". If two things are identical, they have the same identity; they are same thing. If they are equivalent, one can be substituted for the other without affecting the outcome; they have the same behavior and properties.
Identity: Two references to the same object (o1 == o2).
Equality: The method o1.equals( o2 ) returns true. This doesn't necessarily mean that the two objects contain (all) the same data.
In theory it's possible to override a method equals() to return false even for identical objects. But this would break the specification of Object.equals():
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
Identity concept is quite philosophical, that's why you shouldn't reconduce it just to references.
You can say that two identities are the same if a change to the first is reflected on the second and vice-versa. Of course this includes also sharing the same memory address but in general while identity is related to the attributes of the object, equality is used to check whenever two objects are identical, but this doesn't include identity.
The viceversa is quite obvious, if two items have the same identity they are also equal (in equality terms of being interchangeable).
For primitive types ( int , boolean , char, long , float ... )
== and != is equality test
and for Objects
== and != is identity test. [ it compares only the reference ]
equals method is used for equality test of Objects [ it can be overridden to compare specific attributes]
i found an excellent article on this
http://www.cs.cornell.edu/courses/cs211/2006sp/Lectures/L14-Comparison/L14cs211sp06.pdf
http://ocw.mit.edu/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-170Fall-2005/D659DC53-FB1D-403C-8E35-2CAECBED266E/0/lec12.pdf
Quote
I like pigs. Dogs look up to us. Cats look down on us. Pigs treat us as equals. :D
Sir Winston Churchill
x == y is true only if there's the same object referenced by variables x and y.
x.equals(y) depends on the implementation of x.equals(), and is usually less strict that the above, as it compares the content of the object. (In Java, if x.equals(y), it must also be true that x.hashCode() == y.hashCode();)
Example:
Integer w = new Integer(3);
Integer x = new Integer(1);
Integer y = x;
Integer z = new Integer(1);
// all of these evaluate to true
y.equals(x) // it's the same object, of course the content is same
x.equals(z) // different objects, same content (`1`)
z.equals(y)
!w.equals(x); // the content is different (`3` vs `1`)
!w.equals(y);
!w.equals(z);
x == y // same object
z != x // different objects
y != z
w != x
Identical vs. Equal objects
Two objects are said to have identical states (deep equality) if the graphs representing their states are identical in every respect, including the OIDs at every level.
Two objects are said to have equal states (shallow equality) if the graphs representing their states are same, including all the corresponding atomic values. However, some corresponding internal nodes in the two graphs may have objects with different OIDs.
Example: This example illustrates the difference between the two definitions for comparing object
states for equality.
o2 = (i 2 , tuple, <a 1 :i 5 , a 2 :i 6 >)
o3 = (i 3 , tuple, <a 1 :i 4 , a 2 :i 6 >)
o4 = (i 4 , atom, 10)
o5 = (i 5 , atom, 10)
o6 = (i 6 , atom, 20)
In this example, the objects o1 and o2 have equal states (shallow equality), since their states at the atomic level are the same but the values are reached through distinct objects o 4 and o 5 .
However, the objects o1 and o3 have identical states (deep equality), even though the objects themselves are not because they have distinct OIDs. Similarly, although the states of o4 and o5 are identical, the actual objects o4 and o5 are equal but not identical, because they have distinct OIDs.
To add, identity is also known as referential check (references to objects, get it?) and equality as structural check by some authors. At the end of the day an object in memory abstract is just a map/table structure indexed at certain memory address. There can be one or many references (memory addresses) pointing to it. They all are referential-ly identical. When contents of same object is copied to another counterpart then both are structurally equal.
Related
I have list of 2 hibernate entities.
I need to compare them. When I use equals() it always gives false as its reference is different.
E1.equals(E2)
It's because you're taking a reference to the List object only when evaluating equality. You would have to iterate through the collections to check (assuming the ordering is important):
E1.size() == E2.size() && IntStream.range(0, E1.size())
.allMatch(index -> E1.get(index).equals(E2.get(index)));
P.S.1: Variable names are written lowercase in java.
P.S.2: Make sure you're defining equals and hashCode properly. By default same entity is not equal in different states (managed, detached).
This question already has answers here:
Comparing references in Java
(5 answers)
Closed 7 years ago.
I am looking for a Java equivalent of pointer-comparison in C/C++.
Suppose I am invoking a getSomething() method of an object of a class from a third-party. How do I know if the implementation of the getSomething() is just returning the same instance everytime or returning a different instance of the object?
I am not looking to check whether two objects are identical, but need to check if they are the same instance or not. The motivation is, if the 3rd party implementation is creating a new instance everytime, probably I can optimize my code by not invoking the method everytime. Assume getSomething() is invoked by me 1000s of times a second at run-time
From what I read from various articles, I shouldn't rely on hashCode(). In that case what is the way to do this?
Reference types are "pointing to" the same object, when they are equivalent according to the == (identity) operator.
The question says:
I am not looking to check whether two objects are identical, but need to check if they are the same instance or not (emphasis mine)
You actually mixed equality with identity (as I did initially in the answer). Being the same instance is identity. Being the same value is equality.
The == operator compares the values held by the two operands. If the operands are primitive, the actual values are checked for equality. If the operands are of object type, then == checks for equality of identity, functioning in this role just like Python's is keyword.
Note that there is bit of fudginess caused by autboxing and autounboxing between primitive and wrapper object types.
== double equal operator are use to check whether two reference variable hold the same object or not.
Eg.
String s1 = new String("hello");
String s2 = s1;
String s3 = new String("hello");
System.out.println(s1==s2); // it prints true
System.out.println(s1==s3); // it prints false
s1 and s2 pointing to the same object.
s3 holds newly created object and hence s1 == s3 prints false
I think you're not looking for the ==operator. To compare two instances of an object, for example, I use the equals() Object method. Here are two useful links about comparisons:
java ==, equals(), compare(), compareTo()
Javadocs equals() method
You can use == operator to compare two objects if they are having same reference or not.
With respect to 3 contracts mentioned below:
1) Whenever hashCode() is invoked on the same object more than once during an execution of an application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
From this statement, i understand that, In a single execution of an application, if hashCode() is used one or more times on same object it should return same value.
2) If two objects are equal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce the same integer result.
From this statement, i understand that, to perform the equality operation(in broad scope) in your subclass, There are at least four different degrees of equality.
(a) Reference equality(==), comparing the internal address of two reference type objects.
(b) Shallow structural equality: two objects are "equals" if all their fields are ==.
{ For example, two SingleLinkedList whose "size" fields are equal and whose "head" field point to the same SListNode.}
(c) Deep structural equality: two objects are "equals" if all their fields are "equals".
{For example, two SingleLinkedList that represent the same sequence of "items" (though the SListNodes may be different).}
(d) Logical equality. {Two examples:
(a) Two "Set" objects are "equals" if they contain the same elements, even if the underlying lists store the elements in different orders.
(b) The Fractions 1/3 and 2/6 are "equals", even though their numerators and denominators are all different.}
Based on above four categories of equality, second contract will hold good only: if(Say) equals() method returns truth value based on logical_equality between two objects then hashCode() method must also consider logical_equality amidst computation before generating the integer for every new object instead of considering internal address of a new object.
But i have a problem in understanding this third contract.
3) IT IS NOT REQUIRED that if two objects are unequal according to the equals(Object) method, then calling the hashCode() method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
In second contract, As we are saying that hashCode() method should be accordingly[for ex: considering logical_equality before generating integer] implemented, I feel, It is not true to say that, if two objects are unequal according to equals(Object) then hashCode() method may produce same integer results as mentioned in third contract? As per the argument in second contract, hashCode() must produce distinct integer results. One just writing return 42 in hashCode() is breaking second contract!
please help me understand this point!
It would be impossible for hashCode() to always return different values for unequal objects. For example, there are 2^64 different Long values, but only 2^32 possible int values. Therefore the hashCode() method for Long has to have some repeats. In situations like this you have to try hard to ensure that your hashCode() method distributes values as evenly as possible, and is unlikely to produce repeats for the instances you are most likely to use in practice.
The second condition just says that two equal() instances must return the same hashCode() value, so this program must print true:
Long a = Long.MIN_VALUE;
Long b = Long.MIN_VALUE;
System.out.println(a.hashCode() == b.hashCode()); // a.equals(b), so must print true.
However this program also prints true:
Long c = 0L;
Long d = 4294967297L;
System.out.println(c.hashCode() == d.hashCode()); // prints true even though !c.equals(d)
hashCode() does not have to produce a distinct result. return 0; is a perfectly legal implementation of hashCode() - it ensures that two equal objects will have the same hash code. But it will ensure dismal performance when using HashMaps and HashSets.
It's preferable that hashCode() return values will be distinct (i.e., objects that are not equal should have different hash codes), but it's not required.
The second contract states what happens when equals() returns true. It does not say anything about the case when equals() returns false.
The third contract is just a reminder about that fact. It reminds you that when equals() is false for two objects, there is no connection between their hash codes. They may be same or different, as the implementation happens to make them.
The third point means that you can have many unequal objects with the same hashcode. . For example 2 string objects can have the same hashcode. The second point states that two equal objects must have the same hashcode. . return 5 is a valid hash implementation because it returns the same value for 2 equal objects.
Question: if there are two objects o1 and o2 such that o1.equals(o2), what is java's standard convention about the relationship between o1.hashCode() == o2.hashCode()?
Answer: o1.hashCode() == o2.hashCode()
I don't know why..what i thought was since o1 and o2 are different objects, they shouldn't have the same hashCode. If what the question says were o1 == o2, then I would say they have the same hashCode since both o1 and o2 point to the same object.
Can anyone point out what I did wrong?
.equals is used to evaluate the value of an object. When objects are hashed, their numerical values on a systems level are used to produce a hash code (an integer, if you will). If the objects are the exact same (e.g. in terms of attributes), they will have the same numerical sequence and therefore hash to the same value.
Equals and Hashcode always go hand in hand. If o1 == o2, then they point to the same memory and hashcodes are trivially equal. However, one you implement Equals, you always have to make sure that when Equals returns true, Hashcode must return the same value.
Here are the official docs which set out the requirements/standards.
This question already has answers here:
Weird Integer boxing in Java
(12 answers)
What is the difference between == and equals() in Java?
(26 answers)
Closed 9 years ago.
Consider the following Java code:
Object a = new Integer(2);
Object b = new Integer(2);
System.out.println(a.equals(b));
Object x = new Object();
Object y = new Object();
System.out.println(x.equals(y));
The first print statement prints true and the second false.
If this is an intentional behavior, how this helps programming in Java?
If this is not an intentional behavior, is this a defect in Java?
I'm going to answer your question with reservations, but you should know that you are hurting yourself if the intent of the question was to get you to learn and your solution was to ask StackOverflow. That aside...
This behavior is intentional.
The default equals() method on java.lang.Object compares memory addresses, which means that all objects are different from each other (only two references to the same object will return true).
java.lang.Integer overrides this to compare the value of the Integers, so two different Integers both representing the number two compare equal. If you used == instead, you would get false for both cases.
Standard practice in Java is to override the equals method to return true for objects which have the same logical value, even if they were created at different times (or even with different parameters). It's not very useful to have objects representing numbers if you don't have a way to ask, "do these two things represent the same value?".
Incidentally, and this is a tangent here, Java actually keeps a cache of Integer objects for small values. So sometimes you may get two Integer objects where even the == operator will return true, despite you getting them from two different sources. You can even get code that behaves differently for larger integers than it does for smaller, without having it look at the integral values!
This is intended behaviour.
Object.equals() considers the object identity (i.e. an object is only equal to itself), which is the only thing you can do for generic objects.
Integer overrides the method to depend on the integer value, since two Integer objects with the same value are logically equal. Many other classes also override equals() since it's a core mechanism of the standard API and a lot of functionaliy e.g. in the collections framework depends on it.
Why do are you puzzled by the behaviour anyway? Most people are only confused by the == operator not behaving like that (it works like Object.equals()).
The equals method in Java serves a specific purpose: it determines if the objects are logically equal, i.e. their content is the same, whatever that may mean in the context of each specific class. This is in contrast to the objects being the same: two different objects could be logically equivalent.
Going back to your example, a and b are different objects that represent the same logical entity - an integer value of 2. They model the same concept - an integer number, and integer numbers with the same value are identical to each other. a and b are, therefore, equal.
The x and y objects, on the other hand, do not represent the same logical entity (in fact, they do not represent anything). That's why they are neither the same nor are equivalent.
It is intentional, of course.
When comparing Integer objects, equals returns true if their values (in your case, 1) are equal.
Applied on different objects of type Object, it returns false.
x.equals(x)
would return true.
See also Object.equals() doc. By the way, consider using Integer.valueOf(2) rather than new Integer(2) as it reduces memory footprint.
One last funny thing Integer.valueOf(2)==Integer.valueOf(2) will return true but Integer.valueOf(2000)==Integer.valueOf(2000) will return false because in the first case you will receive twice the same instance of the Integer object (there is a cache behind) but not in the second case because the cache is only for values between -127 to 128