Reputation: 21
I am attempting to understand how "equals()" works in Java. Especially in contrast to "toString()". Here is an example that is throwing me off course.
public class Car
{
String make, model;
public Car( String model, String make )
{
this.make = model;
this.model = make;
}
public String toString()
{
String str = "This is a car. ";
str += "Make: " + make + " | Model: " + model;
return str;
}
public boolean equals( Car c )
{
return ( make.equals( c.make ) && model.equals( c.model ) );
}
}
public class Node
{
protected Object obj;
protected Node next;
public Node( Object o )
{
this.obj = o;
this.next = null;
}
public String toString()
{
return obj.toString();
}
public boolean equals( Node n )
{
return ( this.obj.equals( n.obj ) );
}
}
Car c1 = new Car("toyota", "corolla");
Car c2 = new Car("toyota", "corolla");
Node nC1 = new Node( c1 );
Node nC2 = new Node( c2 );
nC1.print();
nC2.print();
if( nC1.equals( nC2 ) )
System.out.println("They are equal!");
else
System.out.println("They are NOT equal!");
Here nC1.print() and nC2.print() behaves as expected. Prints:
This is a car. Make: toyota | Model: corolla
This is a car. Make: toyota | Model: corolla
However nC1.equals( nC2 ), prints:
"They are NOT equal!"
In short the question is that I can override "toString()", but not "equals()". What am I missing? I presume there is a simple explanation for this behavior.
Upvotes: 2
Views: 491
Reputation: 21
Got it. Thank you all for the helpful hints and comments. The code works as desired by replacing the equals(..) code in Class Car with the following:
public boolean equals( Object o )
{
if( o instanceof Car )
{
if( make.equals( ((Car)o).make ) && model.equals( ((Car)o).model ) )
return true;
else
return false;
}
else
return false;
}
Upvotes: 0
Reputation: 46960
The method signature is
@Override
public boolean equals(Object o) { ... }
You can't change the parameter type as you attempted to do. A useful pattern for equals in class Foo
is
@Override
public boolean equals(Object o) {
if (o instanceof Foo) {
Foo foo = (Foo)o;
return <expression testing equality of foo and this> ;
}
return false;
}
For your example,
@Override
public boolean equals(Object o)
{
if (o instanceof Car) {
Car car = (Car)o;
return this.make.equals(car.make) && this.model.equals(car.model);
}
return false;
}
Upvotes: 4
Reputation: 36446
Your method signature is public boolean equals( Car c )
. Thus Java doesn't override the equals(Object)
method; instead it overloads it.
Since the equals()
method in Node
is calling Car.equals(Object)
, it uses a different implementation.
You should do this instead:
public boolean equals( Object o )
{
Car c = (Car)o;
return ( make.equals( c.make ) && model.equals( c.model ) );
}
Upvotes: 1
Reputation: 117589
I think you should keep the signature of the method as:
public boolean equals(Object obj)
As a side note: put @Override
annotation within the method you want to override to make sure that you are overriding the right method, otherwise the compiler complains.
Upvotes: 7