Let’s recall some facts relevant to our task:
Object
is an ancestor to all other Java classesObject
defines the method equals
Object
’s method equals
compares the addresses of two objectsObject
’s version of the method equals
equals
method in a Java class must override Object
’s equals
methodequals
method for a class of namesLet’s define an equals
method for the simple class of names below:
/** Name.java by F. M. Carrano
A class of names, each containing a first name and a last name.
*/
public class Name
{
private String first; // First name
private String last; // Last name
/** Creates a name having first and last names.
@param firstName A string giving the name's first name.
@param lastName A string giving the name's last name. */
public Name(String firstName, String lastName)
{
first = firstName;
last = lastName;
} // End constructor
/** @return the entire name as a string. */
public String getName()
{
return first + " " + last;
} // End getName
/** @return the entire name as a string. */
public String toString()
{
return getName();
} // End toString
} // End Name
Name's
equals
method must override Object
’s version, so both methods must have identical headers. The header for the equals
method in Object
is:
public boolean equals(Object other) // Object's version
The following definition of equals
seems to accomplish our goal: it will override the equals
method in Object
because the headers of both methods are the same.
/** Tests whether this name is equal to another name.
@param other Another Name object.
@return true if the names are equal, otherwise false. */
public boolean equals(Object other)
{
Name otherName = (Name)other;
return first.equals(otherName.first) && last.equals(otherName.last);
} // End equals
Notice that we need to cast the other
parameter from Object
to Name
so that we can access Name
’s data fields (first
and last
).
The following version of the Name
class contains the previous definition of equals
and also defines a main
method to test equals
. Click the RUN button below to see what happens:
/** Name.java by F. M. CarranoA class of names, each containing a first name and a last name.*/public class Name{private String first; // First nameprivate String last; // Last name/** Creates a name having first and last names.@param firstName A string giving the name's first name.@param lastName A string giving the name's last name. */public Name(String firstName, String lastName){first = firstName;last = lastName;} // End constructor/** @return the entire name as a string. */public String getName(){return first + " " + last;} // End getName/** @return the entire name as a string. */public String toString(){return getName();} // End toString/** Tests whether this name is equal to another name.@param other Another Name object.@return true if the names are equal, otherwise false. */public boolean equals(Object other){Name otherName = (Name)other;return first.equals(otherName.first) && last.equals(otherName.last);} // End equalspublic static void main(String[] args){Name jamie1 = new Name("Jamie", "Java");Name jamie2 = new Name("Jamie", "Java");Name jamie3 = jamie1;Object jamie4 = jamie1;Object jamie5 = new Name("Jamie", "Java");Name montana = new Name("Montana", "Oakely");System.out.println("jamie1's name is " + jamie1);System.out.println("jamie2's name is " + jamie2);System.out.println("jamie3's name is " + jamie3);System.out.println("jamie4's name is " + jamie4);System.out.println("jamie5's name is " + jamie5);System.out.println("montana's name is " + montana);System.out.println();System.out.println("According to the equals method:");if (jamie1.equals(montana))System.out.println(" jamie1 and montana are equal.");elseSystem.out.println(" jamie1 and montana are not equal.");if (jamie1.equals(jamie2))System.out.println(" jamie1 and jamie2 are equal.");elseSystem.out.println(" jamie1 and jamie2 are not equal.");if (jamie1.equals(jamie1))System.out.println(" jamie1 and jamie1 are equal.");elseSystem.out.println(" jamie1 and jamie1 are not equal.");if (jamie1.equals(jamie3))System.out.println(" jamie1 and jamie3 are equal.");elseSystem.out.println(" jamie1 and jamie3 are not equal.");if (jamie1.equals(jamie4))System.out.println(" jamie1 and jamie4 are equal.");elseSystem.out.println(" jamie1 and jamie4 are not equal.");if (jamie1.equals(jamie5))System.out.println(" jamie1 and jamie5 are equal.");elseSystem.out.println(" jamie1 and jamie5 are not equal.");if (jamie1.equals("Jamie Jones"))System.out.println(" jamie1 and the string \"Jamie Jones\" are equal.");elseSystem.out.println(" jamie1 and the string \"Jamie Jones\" are not equal.");} // End main} // End Name
Our method appears to give us correct results for the Name
objects defined in lines 41 - 46 of the previous program, but we get an exception when the statement at line 88 invokes equals
. That statement is:
if (jamie1.equals("Jamie Jones"))
We are passing a String
object instead of a Name
object to the equals
method, but we didn’t get a syntax error. Why not? The method’s parameter other
has the data type Object
, and so it can accept an object of any type!
The exception will actually occur at line 35 of Name
’s equals
method. That line is:
Name otherName = (Name)other;
Since other
references a String
object, it can’t be cast to a Name
object; so, we will get an exception (the ClassCastException
) that is fatal.
To ensure that the argument passed to the equals
method is an object of the same class as the invoking object, use the Java operator instanceof
.
For example, the expression
other instanceof Name
is true if other
references an object of either the class Name
or a class derived from Name
. Otherwise, the expression will be false. Thus, our revised equals
method appears as follows:
public boolean equals(Object other)
{
boolean result = false;
if (other instanceof Name)
{
Name otherName = (Name)other;
result = first.equals(otherName.first) &&
last.equals(otherName.last);
} // End if
return result;
} // End equals
See how the method behaves by running the next program:
/** Name.java by F. M. CarranoA class of names, each containing a first name and a last name.*/public class Name{private String first; // First nameprivate String last; // Last name/** Creates a name having first and last names.@param firstName A string giving the name's first name.@param lastName A string giving the name's last name. */public Name(String firstName, String lastName){first = firstName;last = lastName;} // End constructor/** @return the entire name as a string. */public String getName(){return first + " " + last;} // End getName/** @return the entire name as a string. */public String toString(){return getName();} // End toString/** Tests whether this name is equal to another name.@param other Another Name object.@return true if the names are equal, otherwise false. */public boolean equals(Object other){boolean result = false;if (other instanceof Name){Name otherName = (Name)other;result = first.equals(otherName.first) &&last.equals(otherName.last);} // End ifreturn result;} // End equalspublic static void main(String[] args){Name jamie1 = new Name("Jamie", "Java");Name jamie2 = new Name("Jamie", "Java");Name jamie3 = jamie1;Object jamie4 = jamie1;Object jamie5 = new Name("Jamie", "Java");Name montana = new Name("Montana", "Oakely");System.out.println("jamie1's name is " + jamie1);System.out.println("jamie2's name is " + jamie2);System.out.println("jamie3's name is " + jamie3);System.out.println("jamie4's name is " + jamie4);System.out.println("jamie5's name is " + jamie5);System.out.println("montana's name is " + montana);System.out.println();System.out.println("According to the equals method:");if (jamie1.equals(montana))System.out.println(" jamie1 and montana are equal.");elseSystem.out.println(" jamie1 and montana are not equal.");if (jamie1.equals(jamie2))System.out.println(" jamie1 and jamie2 are equal.");elseSystem.out.println(" jamie1 and jamie2 are not equal.");if (jamie1.equals(jamie1))System.out.println(" jamie1 and jamie1 are equal.");elseSystem.out.println(" jamie1 and jamie1 are not equal.");if (jamie1.equals(jamie3))System.out.println(" jamie1 and jamie3 are equal.");elseSystem.out.println(" jamie1 and jamie3 are not equal.");if (jamie1.equals(jamie4))System.out.println(" jamie1 and jamie4 are equal.");elseSystem.out.println(" jamie1 and jamie4 are not equal.");if (jamie1.equals(jamie5))System.out.println(" jamie1 and jamie5 are equal.");elseSystem.out.println(" jamie1 and jamie5 are not equal.");if (jamie1.equals("Jamie Jones"))System.out.println(" jamie1 and the string \"Jamie Jones\" are equal.");elseSystem.out.println(" jamie1 and the string \"Jamie Jones\" are not equal.");} // End main} // End Name
Name
’s equals
method now behaves well regardless of the data type of its argument.