Why .equals method is failing on two same value objects?
I have created a value object MarketVO
and two instances of this value object have same elements and same value for each element.
My value object class is:
public class MarketVO {
private dou开发者_如何学JAVAble floatAmt;
private Date marketDate;
private long marketCap;
}
Here are the values:
returnedData:
FloatAmt: 247657.5418618201, MarketCap: 5249164,
MarketDate: 2011-07-29 00:00:00.0
expectedData:
FloatAmt: 247657.5418618201, MarketCap: 5249164,
MarketDate: 2011-07-29 00:00:00.0
Now in my unit test class, I want to assert that my returned and expected type is same containing same value in same order so am doing something like
assertTrue(returnedData.equals(expectedData))
, now this is returning false
value but if I do
assertEquals(testObject.getfloatAmt(), testObject2.getfloatAmt());
assertEquals(testObject.getmarketCap(), testObject2.getmarketCap());
assertEquals(testObject.getmarketDate(), testObject2.getmarketDate());
this test passes and so am not sure as to why .equals
method is not working in here? Any suggestions?
Update: I want to put emphasize here that we are using this for doing Unit Testing.
The default implementation of .equals
compares object references, not object content.
You probably want to override the equals (and hashCode) methods. Something like this:
public class MarketVO {
private double floatAmt;
private Date marketDate;
private long marketCap;
@Override
public boolean equals(Object o) {
if (!(o instanceof MarketVO))
return false;
MarketVO other = (MarketVO) o;
return other.floatAmt == floatAmt &&
other.marketDate.equals(marketDate) &&
other.marketCap == marketCap;
}
@Override
public int hashCode() {
...
}
}
Use rather the org.apache.commons library which gives you sophisticated ways implement those valuable methods well. The same library also contains ToStringBuilder which is very handy too.
Maven dependency => commons-lang3 (org.apache.commons)
class WhatEver{
...
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, false);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false);
}
...
}
The equals
method doesn't work as you didn't override it for your required behaviour. The default behaviour on Object
(which your class inherits from) is to compare references. Two different instances have different references, thus the equals
fails.
By default .equals()
checks identity and not equality. Change and add this code to your class
@Override
public boolean equals(Object o) {
if(this == o) {
return true;
}
if(o == null || getClass() != o.getClass()) {
return false;
}
MarketVO marketVO = (MarketVO) o;
if(Double.compare(marketVO.floatAmt, floatAmt) != 0) {
return false;
}
if(marketCap != marketVO.marketCap) {
return false;
}
if(marketDate != null ? !marketDate.equals(marketVO.marketDate) : marketVO.marketDate != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result;
long temp;
temp = floatAmt != +0.0d ? Double.doubleToLongBits(floatAmt) : 0L;
result = (int) (temp ^ (temp >>> 32));
result = 31 * result + (marketDate != null ? marketDate.hashCode() : 0);
result = 31 * result + (int) (marketCap ^ (marketCap >>> 32));
return result;
}
I highly recommend using Lombok annotation @EqualsAndHashcode
, it really helps to avoid bugs with equals
and hashCode
methods.
It creates equals and hashCode methods using all non-static non-transient fields by default, but you can specify other behaviors like excluding some fields:
@EqualsAndHashCode(exclude={"fieldsThat", "dontMather"})
or including only some fields:
@EqualsAndHashCode(of={"onlyFields", "thatMather"})
the hashes are different because they are different instances
More precisely the default behaviour is to compare object's addresses in memory (true if the references point to the exactly same object (address) in memory). So override these methods the get the required behaviour.
精彩评论