John Smith
John Smith

Reputation: 21

Override equals() in Java

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

Answers (4)

John Smith
John Smith

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

Gene
Gene

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

tskuzzy
tskuzzy

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

Eng.Fouad
Eng.Fouad

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

Related Questions