I am having a problem with overriding equals method in one class, this class has only one attribute which is a 2-dimensional array called grid. This is the constructor:
public World(int n, int m){
this.grid = new Object[n][m];
}
The equals method:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (null == obj)
return false;
if ( !obj instanceof World)
return false;
World other = (World) obj;
if ( !Arrays.deepEquals(grid, other.grid))
return false;
return true;
}
I have already overridden the hashCode() method as well, but the problem is that doesn't matter the case, the equals is always returning true. Does anyone know what is wrong?
Be careful - you're messing with Object here.
Regardless of the actual objects you place into that array, they will all be using Object#equals for its comparison. The reason for that lies in the documentation of Arrays#deepEquals.
Two possibly null elements e1 and e2 are deeply equal if any of the following conditions hold:
e1 and e2 are both arrays of object reference types, and Arrays.deepEquals(e1, e2) would return true
e1 and e2 are arrays of the same primitive type, and the appropriate overloading of Arrays.equals(e1, e2) would return true.
e1 == e2
e1.equals(e2) would return true.
And...guess what Object#equals does:
public boolean equals(Object obj) {
return (this == obj);
}
Your arrays will only ever be equivalent if and only if they contain the exact same instances of stuff between them.
Applying stricter types around your array, such as a concrete class, may help you to get around the issue. We don't know what you're storing in that array, so I can't suggest anything concrete, but look to move away from Object.
Try this-
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof World)) {
return false;
}
World other = (World) obj;
if (!Arrays.deepEquals(this.grid, other.grid))
return false;
return true;
}
Related
Does somebody know why this test fails? These are 2 identical objects with content inside, if I add the toString method after each Pair the test will pass. I tried to override the Equals method from the Object class but still nothing. Any help will be great, thanks
#Override
public int hashCode() {
return Objects.hash(key, value);
}
#Override
public boolean equals(Object obj) {
return super.equals(obj);
}
Pair Class Code
Error assertEquals
They are actual identical
Your problem is that your override of equals doesn't do anything - it just calls the implementation that you overrode. In other words, it has no effect.
You need to override equals in a way that does the comparison that you need. In other words, your equals needs to
check that the Object being compared to is also a Pair,
call equals for the two key fields,
call equals for the two value fields.
If any of these conditions fail, your equals should return false.
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return key.equals(pair.key) && value.equals(pair.value);
}
This code resolved problem :)
After researching I still can't find the specific solution for my problem. I have an "approximately equals" method that uses an epsilon, while my hashCode method uses the exact values. This breaks the precondition of HashSet when I compare the values.
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof EPoint)) {
return false;
}
EPoint ePoint = (EPoint) o;
return Math.abs(Math.abs(ePoint.lat) - Math.abs(lat)) < EPSILON && Math.abs(Math.abs(ePoint.lon) - Math.abs(lon)) < EPSILON;
}
#Override
public int hashCode() {
return Objects.hash(lat, lon);
}
I can't find a way to make the hasCode() consistent with my equals method.
Your equals itself breaks the contract even before you get to hashCode because it isn't transitive.
This also immediately leads to the only consistent hashCode implementation being to return a constant, because for any two points there is a (very long) chain of intermediate points so that
every two neighbors are equal, therefore
every two neighbors must have the same hashCode, therefore
beginning and end must have the same hashCode.
Now, this is a consistent implementation, but quite obviously a useless one.
I agree with Kayaman: The way your equals methos is implemented, you can have three EPoints (pointA,pointB,and pointC) with:
pointA.equals(pointB) //true
pointA.equals(pointC) //true
pointB.equals(pointC) //false
And this is not allowed. Creating a method with another name might be a solution.
If, however, you need your "almost Equal" objects to have the same hashcode, you could try a different approach:
Map every EPoint to an EPoint out of a grid. If, e.g. your EPoint's lat and lon where floats, you could map each EPoint to an EPoint with the rounded int-values.
If you need higher precision, you could extend on that and go into first, second,...decimal place).
If you do the equals() and the hashcode() method against the "mapped" Point, this should satisfy all requirements:
#Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof EPoint)) {
return false;
}
EPoint ePoint = (EPoint) o;
return this.gridLon() == ePoint.gridLon() && ePoint.gridLat() == this.gridLat();
}
#Override
public int hashCode() {
return Objects.hash(this.gridLon(), this.gridLat());
}
Here's how the site suggests you to write an equals() method.
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MyType)) {
return false;
}
MyType lhs = (MyType) o;
return primitiveField == lhs.primitiveField &&
referenceField.equals(lhs.referenceField) &&
(nullableField == null ? lhs.nullableField == null
: nullableField.equals(lhs.nullableField));
}
Now, I am surely misunderstanding something, but suppose you have two MyType objects m1 and m2, and e.g. if m1.referenceField is null, this is not going to work, because when it reaches
referenceField.equals(lhs.referenceField)
it will throw a NullPointerException. Where could be my logic error?
I believe the point is that this would be a type where referenceField was guaranteed to be non-null, e.g. it's checked in the constructor.
Compare this with nullableField, where the nullity is checked as part of equals.
I am comparing two objects in Java and have implemented equals and hashcode.
Though the objects are equal the comparison returns false.
I found that in the equals implementation it's printing the class of the two objects as different although they are same.
For one it prints: com.salebuild.model.TechnologyProduct
While for the other it prints: com.salebuild.model.TechnologyProduct_$$_javassist_71
So it fails in this condition in the equals method:
if (getClass() != obj.getClass())
{
return false;
}
Unable to find why it's appending this string: _$$_javassist_71
How can I overcome this? Could anyone suggest?
Use instanceof to check if both objects are of the same class.
Here is the code Eclipse offers to check object equality:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof LdapUserDetails)) //check class here
return false;
// check fields for equality here
}
I would write something like that instead:
if (!(this instanceof TechnologyProduct))
{
return false;
}
I have below Findbugs error for my "equal" method,
This class defines an equals method
that overrides an equals method in a
superclass. Both equals methods
methods use instanceof in the
determination of whether two objects
are equal. This is fraught with peril,
since it is important that the equals
method is symmetrical (in other words,
a.equals(b) == b.equals(a)). If B is a
subtype of A, and A's equals method
checks that the argument is an
instanceof A, and B's equals method
checks that the argument is an
instanceof B, it is quite likely that
the equivalence relation defined by
these methods is not symmetric.
I can not post the code here for security violataion. Please let me know what is the error?
It says that the contract of equals() implies that, a.equals(b) is true if and only if b.equals(a) is true.
If B extends A, in A.equals(Object obj) you probably will have
if !(obj instanceof A) return false;
and in B.equals(Object obj) you will have
if !(obj instanceof B) return false;
Here is the asymmetry: an instance of B makes (b instanceof A) true, while an instance of A makes (a instanceof B) false. So it means a risk than a.equals(b) is true and b.equals(a) is false.
You can use the similar construction to prevent this error:
public boolean equals(final Object obj)
{
if (obj == null || getClass() != obj.getClass())
{
return false;
}
// ...
instead of
public boolean equals(final Object obj)
{
if (!(o instanceof UniversalIDDefinition))
{
return false;
}
// ...
You can use this too :
if (obj == null || !MyClass.class.isAssignableFrom(obj.getClass())) {
return false;
}