Apache Common-Lang HashCodeBuilder及EqualsBuilder分析

 

1.1 org.apache.commons.lang.builder.HashCodeBuilder

Reference to Javadoc

介紹:

屬於Apache Common Lang項目下的類,作用是實現Object中的hashCode方法。

Assists in implementing Object.hashCode() methods.

This class enables a good hashCode method to be built for any class. It follows the rules laid out in the book Effective Java by Joshua Bloch. Writing a good hashCode method is actually quite difficult. This class aims to simplify the process.

如何使用(how to use

The following is the approach taken. When appending a data field, the current total is multiplied by the multiplier then a relevant value for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.

All relevant fields from the object should be included in the hashCode method. Derived fields may be excluded. In general, any field used in the equals method must be used in the hashCode method.

To use this class write code as follows:

 public class Person {

   String name;

   int age;

   boolean smoker;

   ...

 

   public int hashCode() {

     // you pick a hard-coded, randomly chosen, non-zero, odd number

     // ideally different for each class

     return new HashCodeBuilder(17, 37). --基數,增數

       append(name). --〉計算公式:17*37 + name

       append(age).

       append(smoker).

       toHashCode();

   }

 }

If required, the superclass hashCode() can be added using appendSuper(int).

Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are usually private, the method, reflectionHashCode, uses AccessibleObject.setAccessible to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are set up correctly. It is also slower than testing explicitly.

A typical invocation for this method would look like:

 public int hashCode() {

   return HashCodeBuilder.reflectionHashCode(this);

 }

 

HashCodeBuilder類中值得學習的一個方法:

public HashCodeBuilder append(Object object) {

        if (object == null) {

            iTotal = iTotal * iConstant;

 

        } else {

            if(object.getClass().isArray()) {

                // 'Switch' on type of array, to dispatch to the correct handler

                // This handles multi dimensional arrays

                if (object instanceof long[]) {

                    append((long[]) object);

                } else if (object instanceof int[]) {

                    append((int[]) object);

                } else if (object instanceof short[]) {

                    append((short[]) object);

                } else if (object instanceof char[]) {

                    append((char[]) object);

                } else if (object instanceof byte[]) {

                    append((byte[]) object);

                } else if (object instanceof double[]) {

                    append((double[]) object);

                } else if (object instanceof float[]) {

                    append((float[]) object);

                } else if (object instanceof boolean[]) {

                    append((boolean[]) object);

                } else {

                    // Not an array of primitives

                    append((Object[]) object);

                }

            } else {

                iTotal = iTotal * iConstant + object.hashCode();

            }

        }

        return this;

    }

 

1.2 org.apache.commons.lang.builder.EqualsBuilder

Reference to Javadoc

介紹:

屬於Apache Common Lang項目下的類,作用是實現Object中的equals方法。

Assists in implementing Object.equals(Object) methods.

如何使用(how to use

This class provides methods to build a good equals method for any class. It follows rules laid out in Effective Java , by Joshua Bloch. In particular the rule for comparing doubles, floats, and arrays can be tricky. Also, making sure that equals() and hashCode() are consistent can be difficult.

Two Objects that compare as equals must generate the same hash code, but two Objects with the same hash code do not have to be equal.

All relevant fields should be included in the calculation of equals. Derived fields may be ignored. In particular, any field used in generating a hash code must be used in the equals method, and vice versa.

Typical use for the code is as follows:

 public boolean equals(Object obj) {

   if (obj == null) { return false; }

   if (obj == this) { return true; }

   if (obj.getClass() != getClass()) {

     return false;

   }

   MyClass rhs = (MyClass) obj;

   return new EqualsBuilder()

                 .appendSuper(super.equals(obj))

                 .append(field1, rhs.field1)

                 .append(field2, rhs.field2)

                 .append(field3, rhs.field3)

                 .isEquals();

  }

Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are usually private, the method, reflectionEquals, uses AccessibleObject.setAccessible to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions are set up correctly. It is also slower than testing explicitly.

A typical invocation for this method would look like:

 public boolean equals(Object obj) {

   return EqualsBuilder.reflectionEquals(this, obj);

 }

原理:

public EqualsBuilder append(int lhs, int rhs) {

        if (isEquals == false) {

            return this;

        }

        isEquals = (lhs == rhs);

        return this;

}

從這個方法中可以看出,EqualsBuilder類中有一個成員變量isEquals,代表當前的比較結果,所以在append的時候,只要中間有一步比較失敗時,後面的就不用再比了。

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章