Chairperson and Program Coordinator for the Computer Science Technology Program at Dawson College Instructor and Program Consultant for the School of Extended Learning Computer Institute at Concordia University I have been passionate about programming since buying an Apple][+ in 1980. I paid the extra $450 to bring the RAM up to 48K! Ken has posted 17 posts at DZone. You can read more from them at their website. View Full User Profile

NetBeans in the Classroom: Mandatory Methods for Beans (Part 2)

07.09.2014
| 2262 views |
  • submit to reddit
Ken Fogel is the Program Coordinator and Chairperson of the Computer Science Technology program at Dawson College in Montreal, Canada. He is also a Program Consultant to and part-time instructor in the Computer Institute of Concordia University's School of Extended Learning. He blogs at omniprogrammer.com and tweets @omniprof. His regular columns about NetBeans in education are listed here.


In this next article about beans and beginners, following on from part 1, I present three more mandatory methods. The first two are methods we override from the Object super class and they are equals and hashCode. The last requires that an interface is added, Comparable, and the method is compareTo.

equals() and hashCode()

These two methods go together like fish and chips. For this reason when, in NetBeans IDE, you choose "Source | Insert Code", they are shown together:

The purpose of the equals method is to determine if the instance of the object invoking the method has the same state as the objects of the same type that is passed to it. Remember that using the equality operator ‘==’ compares the addresses stored in the object references and not the state. The equals method does not need to compare the state of every member of the class. You get to decide what it means to be equals.

For example, if the bean has a key such as when the bean is loaded from a record in a database then the only member to be concerned with is the key. Two records with the same primary key are the same. On the other hand a bean without a guaranteed unique key may require the state of every member to be compared for equality. This also implies that every member of the bean that is itself an object must have an equals method.

In the end it’s pretty obvious that everyone needs an equals method. The hashCode method is not quite so obvious. A hash code in an integer that is calculated based on the values of members that are primitives plus the hash code returned by objects that are members. A hash code is not unique. This puzzled me at first because I could not understand the purpose of a calculated value that might be the same for two different states of the same object type.

The key to understanding the hash code is to know that if two objects of the same type do not have the same hash code they cannot be equal. This is important when you consider that our best friend in code is the integer. More than any other data type we love integers because our CPU lives for integers. Integers are processed faster than any other type. To compare two Strings we need to process every character in each String. If we compared the hash code of each String and they were not the same then there is no need to do any further work.

Only if the hash codes are the same do we need to invoke the equals method. This is why the two always go together. Another important purpose of the hashcode and equals pairing is the hash collections, almost always your first choice for using collections.

Notice that you get to choose which members of the class should be used in the equals and hashcode methods. A word of advice is to always choose the same members for each method. Collections or frameworks that use hashcode before equals will give unpredictable results if the members are different in each method.

For this example I have chosen some of the members.

Here is the code that is produces by NetBeans.

    @Override
    public int hashCode() {
        int hash = 3;
        hash = 13 * hash + Objects.hashCode(this.manufacturer);
        hash = 13 * hash + Objects.hashCode(this.model);
        hash = 13 * hash + this.engineDisplacement;
        hash = 13 * hash + this.cylinders;
        hash = 13 * hash + Objects.hashCode(this.transmission);
        hash = 13 * hash + Objects.hashCode(this.driveTrain);
        hash = 13 * hash + this.weight;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final MyCarBean other = (MyCarBean) obj;
        if (!Objects.equals(this.manufacturer, other.manufacturer)) {
            return false;
        }
        if (!Objects.equals(this.model, other.model)) {
            return false;
        }
        if (this.engineDisplacement != other.engineDisplacement) {
            return false;
        }
        if (this.cylinders != other.cylinders) {
            return false;
        }
        if (!Objects.equals(this.transmission, other.transmission)) {
            return false;
        }
        if (!Objects.equals(this.driveTrain, other.driveTrain)) {
            return false;
        }
        if (this.weight != other.weight) {
            return false;
        }
        return true;
    }

Examining the code generated by NetBeans is a good way to learn even more about coding. Notice the use of the static methods of the Objects (yes there is an ‘s’ at the end) class. This class was added to Java 7 and resolves the problem of null references. What if the String in one object was not initialized? If you invoked its equals or hashcode methods you would get a Null Pointer Exception.

Comparable Interface and compareTo()

The last method I consider mandatory is compareTo. This method’s job is to determine if the object invoking it is less than, equal to, or greater than the object of the same type that is passed to it. Unlike equals there is no hash code optimization. You must decide what constitutes these three conditions and return them as less than zero, zero, or greater than zero, usually as -1, 0, or 1.

There is also only a minimal assist from NetBeans for this method. You are pretty much on your own. The first step is to add the Comparable interface to the class.

public class MyCarBean implements Comparable{

Note the use of generics to ensure that only objects of type MyCarBean can be used in a comparison. Be wary of the fact that this will be just a compile time check and not a run-time check.

Adding this code makes NetBeans declare an error and pointing at the light bulb reveals what it is.

Clicking on the light bulb gives two choices.

Select the first, Implement all abstract methods, and the following code will be added to the class.

    @Override
    public int compareTo(MyCarBean o) {
        throw new UnsupportedOperationException("Not supported yet."); 
    }

The next article will look at how to write a compareTo method!

Published at DZone with permission of its author, Ken Fogel.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)