Override the equals method - java

I'm currently revising for an exam. On a past paper there was the question,
Override the equals method in the following class. The method shall check for
content equality of the whole state.
class Employee
{
String firstName;
int age;
}
[2 marks]
I did some fiddling for the right answer and have come up so far with this. Is there a simpler way to answer the question and is this right? Many thanks for help.
public class Employee
{
int age;
public boolean equals(Object obj)
{
if(this == obj)
{
return true; //Reference equality.
}
if(!(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return firstName == other.firstName;
return age == other.age;
}
}

Use
return (((this.firstName == null || other.firstName == null)
&& this.firstName == other.firstName)
||
this.firstName.equals(other.firstName))
&& age == other.age;
This handles null cases too.

One thing to note, and I wouldn't imagine you would get docked for this in an exam...
It's usually poor practice to do an instanceof when the class isn't final. The reason for that is that equals() must be symmetric. Accepting subclasses (who might also implement equals with their own new aspects) could cause it to not be symmetric.
Example (I think the example is the same used in Effective Java 2ed):
class Point {
protected int x, y;
//equals method uses instanceof Point and checks x and y values are the same
}
class ColorPoint extends Point {
protected Color color;
//equals method checks that it's a ColorPoint, that super.equals is true,
//then checks the Color
}
new Point(1, 2).equals(new ColorPoint(1, 2, Color.red)); //true
new ColorPoint(1, 2, Color.red).equals(new Point(1, 2)); //false
It's a very subtle point that even most of the answerers here didn't take into account. But it's the reason that most generators of equals (such as the one in your favourite IDE) tend to do exact class comparison:
if ( this.getClass() != other.getClass() ) {
return false;
}
When the equals method uses instanceof it's usually a good move to document that subclasses must follow the exact same specification.

A couple of points:
You need to check if obj is null.
To compare String contents in Java, use equals(), i.e. firstName.equals(other.firstName). Check to see if firstName is null first.
Here's an improved implementation:
public boolean equals(Object obj)
{
if(obj == null)
{
return false;
}
if(this == obj)
{
return true; //Reference equality.
}
if(this.getClass() != obj.getClass())
{
return false;
}
Employee other = (Employee) obj;
if(firstName == null)
{
if(other.firstName != null)
{
return false;
}
}
else if(!firstName.equals(other.firstName))
{
return false;
}
return age == other.age;
}
EDIT: Updated type comparison to make equals() symmetric in accordance with #Mark Peters' answer.

The String firstName should be compared with .equals(), NOT ==. The == compare is ok for the primitive int age field.
What if both firstNames are identical, yet age is unequal? Shouldn't this fail?
Something like return (firstName.equals(obj.firstName)) && (age == obj.age);
Of course, that doesn't consider the case when this.firstName is null, which would result in a NullPointerException being thrown.
Are the Employees considered equal if both have null firstNames? What if one is null and the other not? Assuming both must be null, or both must be String.equals(), you could use:
return ((null == firstName && null == obj.firstName)
|| (null != firstName && firstName.equals(obj.firstName)))
&& (age == obj.age);
instead of your 2 return statements. The rest looks ok.

public boolean equals(Object o){
if(this==o){ //same instance, no need to check more
return true;
}
if(o instanceof Employee){ //when null this will yield false
Employee other = (Employee) o;
return (this.name == other.name || (this.name != null && this.name.equals(other.name)) && this.age == other.age;
}
return false;
}

To put together in one answer all the parts already mentioned:
public boolean equals(Object obj) {
if(this == obj) {
return true; //Reference equality.
}
if(obj == null || !(obj instanceof Employee))
{
return false; // not the same type.
}
Employee other = (Employee) obj;
return (firstName.equals(other.firstName) && age == other.age);
}

Your last line, the age comparison, is unreachable; you shouldn't use == to compare Strings; and you need to account for null values.
Since the general movement seems to be towards laying it all out for you, here's Eclipse's implementation:
public class Employee {
private final String firstName;
private final int age;
public Employee(final String firstName, final int age) {
super();
this.firstName = firstName;
this.age = age;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
return result;
}
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Employee other = (Employee) obj;
if (age != other.age) {
return false;
}
if (firstName == null) {
if (other.firstName != null) {
return false;
}
} else if (!firstName.equals(other.firstName)) {
return false;
}
return true;
}
}
And a battery of tests:
import org.junit.Test;
public class EmployeeTest {
#Test
public void testEmployeeEquals() {
final Employee nullNameEmp = new Employee(null, -1);
final Employee empA1 = new Employee("a", 1);
final Employee empA1Clone = new Employee("a", 1);
final Employee empA2 = new Employee("a", 2);
final Employee empB1 = new Employee("b", 1);
final Employee empB2 = new Employee("b", 2);
final Employee subEmp = new Employee("a", 1) {
};
assert !nullNameEmp.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !nullNameEmp.equals(empA2);
assert !nullNameEmp.equals(empB1);
assert !nullNameEmp.equals(empB2);
assert !nullNameEmp.equals(subEmp);
assert !nullNameEmp.equals(null);
assert !empA1.equals(nullNameEmp);
assert empA1.equals(empA1Clone);
assert !empA1.equals(empA2);
assert !empA1.equals(empB1);
assert !empA1.equals(empB2);
assert !empA1.equals(subEmp);
assert !empA1.equals(null);
assert !empA2.equals(nullNameEmp);
assert !empA2.equals(empA1);
assert !nullNameEmp.equals(empA1Clone);
assert !empA2.equals(empB1);
assert !empA2.equals(empB2);
assert !empA2.equals(subEmp);
assert !empA2.equals(null);
assert !empB1.equals(nullNameEmp);
assert !empB1.equals(empA1);
assert !empB1.equals(empA1Clone);
assert !empB1.equals(empA2);
assert !empB1.equals(empB2);
assert !empB1.equals(subEmp);
assert !empB1.equals(null);
assert !empB2.equals(nullNameEmp);
assert !empB2.equals(empA1);
assert !empB2.equals(empA1Clone);
assert !empB2.equals(empA2);
assert !empB2.equals(empB1);
assert !empB2.equals(subEmp);
assert !empB2.equals(null);
assert !subEmp.equals(nullNameEmp);
assert !subEmp.equals(empA1);
assert !subEmp.equals(empA1Clone);
assert !subEmp.equals(empA2);
assert !subEmp.equals(empB1);
assert !subEmp.equals(empB2);
assert !subEmp.equals(null);
assert nullNameEmp.equals(nullNameEmp);
assert empA1.equals(empA1);
assert empA1Clone.equals(empA1Clone);
assert empA2.equals(empA2);
assert empB1.equals(empB1);
assert empB2.equals(empB2);
assert subEmp.equals(subEmp);
}
}

Related

Why is retainAll not accurately computing the intersection of two sets?

I'm using Java 6. I can't figure out why "retainAll" is not correctly computing the intersection of two sets. I have
for (ProductDto dtoProd : dto.getProducts())
{
System.out.println("dtoProd:" + dtoProd.getId());
} // for
for (ProductDto princProd : principal.getProducts())
{
System.out.println("princProd:" + princProd.getId());
} // for
dto.getProducts().retainAll(principal.getProducts());
Despite the fact I observe through my System.out's that I have the same products in both sets, after, the last call, my "dto.getProducts()" is empty. This is the relevant object's id and hashcode methods, if that matters ....
#Override
public int hashCode()
{
return this.id != null ? this.id.hashCode() : 0;
}
#Override
public boolean equals(Object obj)
{
boolean ret = false;
if (obj instanceof ProductDto)
{
final ProductDto other = (ProductDto) obj;
ret = (this.id == other.getId() || (this.id != null && this.id.equals(other.getId())));
}
return ret;
}
and here is the System.out info
dtoProd:777
dtoProd:778
dtoProd:110074257z
princProd:777
princProd:777SB
princProd:110074257z
princProd:110074258z
princProd:110074259z
princProd:6161
princProd:778
What else do I need to do to compute the correct intersection?

Java equals method not behaving as expected

package restaurantclient;
public class Restaurant extends Store {
//Instance Variables
private int peopleServed;
private double averagePrice;
//Constructor with 3 parameters
public Restaurant(String storename, int peopleServed, double averagePrice) {
super(storename);
setPeopleServed(peopleServed);
setAveragePrice(averagePrice);
}
//Getters (Accessors)
public int getPeopleServed() {
return peopleServed;
}
public double getAveragePrice() {
return averagePrice;
}
//Setters (Mutators)
public void setPeopleServed(int peopleServed) {
this.peopleServed = peopleServed;
}
public void setAveragePrice(double averagePrice) {
this.averagePrice = averagePrice;
}
//toString Method [Must Override]
#Override
public String toString() {
String information = "Store name: " + (super.getName());
information += "\n" + "The number of people served: " + peopleServed;
information += "\n" + "The average price per person: $" + averagePrice;
return information;
}
//Equals Method
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!(this.getName().equals(otherRestaurant.getName())))
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed))
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
return true;
}
public double getAverageTaxes() {
double total;
total = this.getPeopleServed() * this.getAveragePrice()
* super.CA_TAX_RATE;
return total;
}
}
package restaurantclient;
public class Store {
//Instance Variables
protected final double CA_TAX_RATE = 0.0884;
private String storename;
//Constructor
public Store(String storename) {
setName(storename);
}
//Getters (Accessors)
public String getName() {
return storename;
}
//Setters (Mutators)
public void setName(String storename) {
this.storename = storename;
}
//toString Method [Must Override]
#Override
public String toString() {
String directory = "Name of store: " + storename;
return directory;
}
//Equals Method
public boolean equals (Store storename) {
if (this == storename)
return true;
if (storename == null)
return false;
if (!(storename instanceof Store))
return false;
return true;
}
}
Above are the equals methods I'm calling. They are displaying the wrong answers: it should be in the first instance, "They are not equal" and in the second instance after setting everything equal to each other, it should display, "They are equal". I have tried very hard on this problem and many things have not worked. There are no overt errors it runs fine, but I am doing something wrong and some precise guidance would be a lot of help. Much of the vague hints have got me nowhere. I need something concrete, if this makes to you. Thanks again for the help. The following is the Client class:
package restaurantclient;
public class RestaurantClient {
public static void main(String[] args) {
Restaurant r1 = new Restaurant("McDonald's", 1000000, 8.00);
Restaurant r2 = new Restaurant("KFC", 500000, 6.00);
System.out.println(r1.toString());
System.out.println(r2.toString());
System.out.println();
r2.setAveragePrice(r1.getAveragePrice());
r2.setPeopleServed(r1.getPeopleServed());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal.");
}
else {
System.out.println("The objects are not equal."); //SHOULD say "not equal" here EVERY TIME the second instance (next comment down) says "Equal"...this should never change.
System.out.println();
}
System.out.println();
r2.setName(r1.getName());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal."); //Now that everything is equal, it should print "The Objects are Equal" but it doesn't. It's in lock-step with the previous instance. Changing some things like return true to return false might make both these instances "Are equal" and some might change them to "Not Equal" but they are never the way I want them, which is when 2 changes are made, they are not equal (first case) and when the third and final change is made (like this case here on this line) it should say "the obj are equal" but it doesn't.
}
else {
System.out.println("The objects are not equal.");
System.out.println();
}
System.out.println();
System.out.print("The avg. annual taxes paid by the restaurant is: $");
System.out.println(r1.getAverageTaxes());
}
}
The reason that I see is simple, you are not getting the same name.
In equals, you are comparing super.getName() with otherRestaurant.getName()
If the superclass of Restaurant have a different format or return an other variable, since you compare it to Restaurant.getName(), this will compare different value. Using this.getName() to compare the same variable (or format of variable) is safer. Even if Restaurant.getName() is only returning the super.getName(), this would be safer if you changed the method of Restaurant (because you prefer it an other way).
Here is an example :
Restaurant:
public String getName(){
return "A restaurant " + name;
}
Super class :
public String getName(){
return name;
}
Will result into comparing "A restaurant : KFC" with "KFV".
Using the same getter assure you to return the same "format".
Aslo, your logic is wrong. You want to check if one of the value is different, if it is, return false. And if you reach the end of the method, meaning there where no difference leading to a return false, you return true.
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!super.getName().equals(otherRestaurant.getName())) // added ! here
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed)) // change to != here
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
//No differences, then it is equals.
return true;
Note :
This condition could be shorten
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
Since it is doing the same thing (comparing the values) :
if (averagePrice != (otherRestaurant.averagePrice))
return false;
Edit :
You are having a problem of overriding.
In Store:
public boolean equals(Store s){}
And in Restaurant
public boolean equals(Object o){}
Since you are calling the method with a Restaurant (subclass of Store), the JVM will use the Store.equals method since it match the type, Restaurant.equals is not overriding it, it override the method in Object. Change to Store.equals(Object o) to correct this.
The method equals comes from Object so it should be always receiving an Object to prevent any problem like this one, if you specify the type in a method, it will not override correctly the method (depending on the type)
Seems you are checking for equality and then returning false, when you should check for not equality to return false.
else if (!super.getName().equals(otherRestaurant.getName()))
return false;
else if (peopleServed != (otherRestaurant.peopleServed))
return false;
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
Also as asked, any reason to uses super.getName() ?
And since peopleServed & averagePrice cannot be null, the -1 check is not needed as the expected result we be the same as the equality check
And finally, I'm guessing the end return should be true, as it means it's different instance of an object, but they have all the same attributs.
Within your equals() method , If super.name() equals otherRestaurant.name() shouldn't you return true, here:
else if (super.getName().equals(otherRestaurant.getName())) return false;
Ok, that one will work in any cases:
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (name == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (name!=otherRestaurant.getName())
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != otherRestaurant.peopleServed)
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != otherRestaurant.averagePrice)
return false;
return true;
}
check it and reply if it is ok

Compact equals and hashcode

I have a bean with 4 attributes:
user
institutionId
groupId
postingDate
I use Eclipse to generate equals and hashcode but the resulting code is not pretty. Is there a compact way to do the same? Assuming I want equals & hashcode to use all the attributes or a subset of them.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((groupId == null) ? 0 : groupId.hashCode());
result = prime * result + ((institutionId == null) ? 0 : institutionId.hashCode());
result = prime * result + ((postingDate == null) ? 0 : postingDate.hashCode());
result = prime * result + ((user == null) ? 0 : user.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ManGroupKey other = (ManGroupKey) obj;
if (groupId == null) {
if (other.groupId != null)
return false;
} else if (!groupId.equals(other.groupId))
return false;
if (institutionId == null) {
if (other.institutionId != null)
return false;
} else if (!institutionId.equals(other.institutionId))
return false;
if (postingDate == null) {
if (other.postingDate != null)
return false;
} else if (!postingDate.equals(other.postingDate))
return false;
if (user == null) {
if (other.user != null)
return false;
} else if (!user.equals(other.user))
return false;
return true;
}
In Java 7
public int hashCode() {
return Objects.hash(groupId, institutionId, postingDate, user);
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
// cast to correct class
Target o = (Target)obj;
return Objects.equals(groupId, o.groupId) &&
Objects.equals(institutionId, o.institutionId) &&
Objects.equals(postingDate, o.postingDate) &&
Objects.equals(user, o.user);
}
You could compact the code down, but the odds are far higher that you would introduce bugs than that you would do anything useful. All the parts of the equals and hash code method are there for a reason.
If it's bothering you most IDEs have a folding editor, just click the little yellow box (usually) and all the contents of the method get hidden away.
Instead of using the eclipse generated code, you can use Apache-common-langs(http://commons.apache.org/proper/commons-lang/) class HashCodeBuilder and EqualsBuilder to do this:
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this);
}
hashCode:
Either:
#Override
public int hashCode() {
return Objects.hash(user, institutionId, groupId, postingDate);
}
Or:
#Override
public int hashCode() {
int result = 17;
result = 31 * result + Objects.hashCode(user);
result = 31 * result + Objects.hashCode(institutionId);
result = 31 * result + Objects.hashCode(groupId);
result = 31 * result + Objects.hashCode(postingDate);
return result;
}
Equals:
public boolean equals(Object obj){
if (obj == this){
return true;
}
if (! (obj instanceof ManGroupKey)){
return false;
}
ManGroupKey other = (ManGroupKey) obj;
return Objects.equals(user, other.user)
&& Objects.equals(institutionId, other.institutionId)
&& Objects.equals(groupId, other.groupId)
&& Objects.equals(postingDate, other.postingDate);
}
You can at least remove one level of nesting by removing the other.x != null check.
Comparing a value in this way: x.equals(y) will always return false when y is null.
Aside from that: the .equals() method is a good example where a bit of reflection can be handy, possible extracted out into a generic utility method. All you have to do is run through the different fields and see if they're equal in the two objects, that can be done in a few lines.
Obviously that is only feasible when you actually want to compare each field (or you'll have to add some additions to it which let you choose the fields).
I think the library, that can suite you is apache common. It provides EqualsBuilder and HashCodeBuilder classes, that do exactly what you are looking for.
Consider this question for details: Apache Commons equals/hashCode builder
Here are some code snippets:
public class Bean{
private String name;
private int length;
private List<Bean> children;
#Override
public int hashCode(){
return new HashCodeBuilder()
.append(name)
.append(length)
.append(children)
.toHashCode();
}
#Override
public boolean equals(final Object obj){
if(obj instanceof Bean){
final Bean other = (Bean) obj;
return new EqualsBuilder()
.append(name, other.name)
.append(length, other.length)
.append(children, other.children)
.isEquals();
} else{
return false;
}
}
}

Remove an element from an array

I need to remove an element of the array based on a match.
Here is my method to remove the event.
public boolean removeEvent(int year, int month, int day, int start, int end, String activity)
{
Event newEvent = new Event(year, month, day, start, end, activity);
for (int i = 0; i < 5; i++)
{
if (newEvent.equals(events[i]))
{
events[i] = null;
newEvent = null;
numEvents--;
}
}
When I try
calendarTest1.removeEvent(2000, 1, 1, 1, 1, "Cal Test 1");
nothing happens. I have an element in my array with those values but it does not change that element to null.
This is for homework so I don't really want to be told how to do it, just why this does not work. Thank you.
Here is my equals method:
public boolean equals(Object obj){
Event someEvent = (Event) obj;
if(
this.date == someEvent.date
&&
this.start == someEvent.start
&&
this.end == someEvent.end
&&
this.activity.equals(someEvent.activity))
if(obj == null)
return false;
if(obj instanceof Event)
return true;
else
{
return false;
}
}
I have tried a lot of different things but I still get the NullPointerException Error
your overridden equal method shoud be somethig like below
#Override
public boolean equals(Object o) {
// If the object is compared with itself then return true
if (o == this) {
return true;
}
/* Check if o is an instance of Event or not
"null instanceof [type]" also returns false */
if (!(o instanceof Event)) {
return false;
}
// typecast o to Event so that we can compare data members
Event e = (Event) o;
// Compare the data members and return accordingly
return year==e.year && month== e.month && day==e.day && start == e.start && end == e.end && activity.equals(e.activity);
}
}
You are comparing two instances in this if event[i] has Event instance then comparison way is different then strings comparison.
You need to override equals method in you class ex:
#Override
public boolean equals(Object ob) {
if (ob == null)
return false;
if (ob instanceof Event) {
Event e = (Event)ob;
return this.someStringValue.equals(e.someStringValueItHas); // compare all values you want like this
}
return false;
}
here we check correct instance of class then its properties if they are equal or not.
is your equals method checking for all the attributes?
public boolean equals(Object o){
if(o == null) return false;
if(o instanceOf Event){
Event givenObject = (Event) o;
if(this.year == givenObject.year)
if(this.month == givenObject.month)
.....
.....
if(this.activity.equals(givenObject.activity)){
return true;
}
}
return false;
}

Regarding Object Comparison

I am having a java class Rec. I have two instance of it Rec1 and Rec2. I want to check whether the values of Rec1 and Rec2 are equal. If i do Rec1.equals(Rec2) is it correct way of doing it?
class Rec {
private BigDecimal RecordId = null;
private BigDecimal recSubNum = null;
private BigDecimal FileId = null;
private String Category = null;
private BigDecimal status = null;
private BigDecimal errorCode = null;
}
You need to implement the equals() and hashCode() methods to implement object equality in Java:
class Rec {
private BigDecimal recordId = null;
private BigDecimal recSubNum = null;
private BigDecimal FileId = null;
private String category = null;
private BigDecimal status = null;
private BigDecimal errorCode = null;
#Override
public int hashCode() {
int ret = 41;
ret = hc(ret, recordId);
ret = hc(ret, recSubNum);
ret = hc(ret, fieldId);
ret = hc(ret, category);
ret = hc(ret, status);
ret = hc(ret, errorCode);
return ret;
}
#Override
public boolean equals(Object ob) {
if (ob == null) return false;
if (ob.getClass() != Rec.class) return false;
Rec r = (Rec)ob;
if (!eq(r.recordId, record)) return false;
if (!eq(r.recSubNum, recSubNum)) return false;
if (!eq(r.fileId, fileId)) return false;
if (!eq(r.category, category)) return false;
if (!eq(r.status, status)) return false;
if (!eq(r.errorCode, errorCode)) return false;
return true;
}
private static boolean eq(Object ob1, Object ob2) {
return ob1 == null ? ob2 == null : ob1.equals(ob2);
}
private static int hc(int hc, Object field) {
return field == null ? hc : 43 + hc * field.hashCode();
}
}
Note: the equals/hashCode contract for Java means that for any two objects a and b:
a.equals(b) == b.equals(a)
and if two objects are equal then a.hashCode() must equal b.hashCode().
Edit: there are two ways of checking if the types match. Either:
if (ob == null) return false;
if (ob.getClass() != Rec.class) return false;
or
if (!(ob instanceof Rec)) return false;
These two do different things and you should select the correct one depending on what you want to do. I generally prefer the first one unless you know you need the second. What's the difference?
class A {
public int i;
public boolean equals(Object ob) {
if (!(ob instanceof A)) return false;
return i == ((A)ob).i;
}
}
Looks reasonable right? What if the class gets extended:
class B extends A {
public int j;
public boolean equals(Object ob) {
if (!(ob instanceof B)) return false;
if (!super.equals(ob)) return false;
return j == ((B)ob).j;
}
}
Still looks reasonable? It's broken.
A a = new A();
a.i = 10;
B b = new B();
b.i = 10;
b.j = 20;
System.out.println(a.equals(b)); // true! Is this really what you want?
System.out.println(b.equals(a)); // false! Different to previous = problem.
That's why I favour getClass() over instanceof unless I really want subclass equality.
if Rec is a user defined class then you really should override the equals method otherwise it will just call the equals method in the Object class;
something like :
public boolean equals(Rec x){
//check here to see if the references are the same, if so return true
if(this == x) return true;
//if they aren't the same object then check all the fields for equality
if (category.equals(x.category) && etc etc) return true;
else return false;
}

Categories

Resources