View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3.builder;
19  
20  import java.lang.reflect.AccessibleObject;
21  import java.lang.reflect.Field;
22  import java.lang.reflect.Modifier;
23  import java.util.Collection;
24  import java.util.HashSet;
25  import java.util.Set;
26  
27  import org.apache.commons.lang3.ArrayUtils;
28  import org.apache.commons.lang3.Validate;
29  
30  /**
31   * <p>
32   * Assists in implementing {@link Object#hashCode()} methods.
33   * </p>
34   *
35   * <p>
36   * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in
37   * the book <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a
38   * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process.
39   * </p>
40   *
41   * <p>
42   * The following is the approach taken. When appending a data field, the current total is multiplied by the
43   * multiplier then a relevant value
44   * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
45   * appending the integer 45 will create a hash code of 674, namely 17 * 37 + 45.
46   * </p>
47   *
48   * <p>
49   * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be
50   * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code>
51   * method.
52   * </p>
53   *
54   * <p>
55   * To use this class write code as follows:
56   * </p>
57   *
58   * <pre>
59   * public class Person {
60   *   String name;
61   *   int age;
62   *   boolean smoker;
63   *   ...
64   *
65   *   public int hashCode() {
66   *     // you pick a hard-coded, randomly chosen, non-zero, odd number
67   *     // ideally different for each class
68   *     return new HashCodeBuilder(17, 37).
69   *       append(name).
70   *       append(age).
71   *       append(smoker).
72   *       toHashCode();
73   *   }
74   * }
75   * </pre>
76   *
77   * <p>
78   * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}.
79   * </p>
80   *
81   * <p>
82   * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
83   * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code>
84   * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
85   * are set up correctly. It is also slower than testing explicitly.
86   * </p>
87   *
88   * <p>
89   * A typical invocation for this method would look like:
90   * </p>
91   *
92   * <pre>
93   * public int hashCode() {
94   *   return HashCodeBuilder.reflectionHashCode(this);
95   * }
96   * </pre>
97   *
98   * <p>The {@link HashCodeExclude} annotation can be used to exclude fields from being
99   * used by the <code>reflectionHashCode</code> methods.</p>
100  *
101  * @since 1.0
102  */
103 public class HashCodeBuilder implements Builder<Integer> {
104     /**
105      * The default initial value to use in reflection hash code building.
106      */
107     private static final int DEFAULT_INITIAL_VALUE = 17;
108 
109     /**
110      * The default multiplier value to use in reflection hash code building.
111      */
112     private static final int DEFAULT_MULTIPLIER_VALUE = 37;
113 
114     /**
115      * <p>
116      * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
117      * </p>
118      *
119      * @since 2.3
120      */
121     private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<>();
122 
123     /*
124      * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
125      * we are in the process of calculating.
126      *
127      * So we generate a one-to-one mapping from the original object to a new object.
128      *
129      * Now HashSet uses equals() to determine if two elements with the same hash code really
130      * are equal, so we also need to ensure that the replacement objects are only equal
131      * if the original objects are identical.
132      *
133      * The original implementation (2.4 and before) used the System.identityHashCode()
134      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
135      *
136      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
137      * to disambiguate the duplicate ids.
138      */
139 
140     /**
141      * <p>
142      * Returns the registry of objects being traversed by the reflection methods in the current thread.
143      * </p>
144      *
145      * @return Set the registry of objects being traversed
146      * @since 2.3
147      */
148     static Set<IDKey> getRegistry() {
149         return REGISTRY.get();
150     }
151 
152     /**
153      * <p>
154      * Returns <code>true</code> if the registry contains the given object. Used by the reflection methods to avoid
155      * infinite loops.
156      * </p>
157      *
158      * @param value
159      *            The object to lookup in the registry.
160      * @return boolean <code>true</code> if the registry contains the given object.
161      * @since 2.3
162      */
163     static boolean isRegistered(final Object value) {
164         final Set<IDKey> registry = getRegistry();
165         return registry != null && registry.contains(new IDKey(value));
166     }
167 
168     /**
169      * <p>
170      * Appends the fields and values defined by the given object of the given <code>Class</code>.
171      * </p>
172      *
173      * @param object
174      *            the object to append details of
175      * @param clazz
176      *            the class to append details of
177      * @param builder
178      *            the builder to append to
179      * @param useTransients
180      *            whether to use transient fields
181      * @param excludeFields
182      *            Collection of String field names to exclude from use in calculation of hash code
183      */
184     private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients,
185             final String[] excludeFields) {
186         if (isRegistered(object)) {
187             return;
188         }
189         try {
190             register(object);
191             final Field[] fields = clazz.getDeclaredFields();
192             AccessibleObject.setAccessible(fields, true);
193             for (final Field field : fields) {
194                 if (!ArrayUtils.contains(excludeFields, field.getName())
195                     && !field.getName().contains("$")
196                     && (useTransients || !Modifier.isTransient(field.getModifiers()))
197                     && !Modifier.isStatic(field.getModifiers())
198                     && !field.isAnnotationPresent(HashCodeExclude.class)) {
199                     try {
200                         final Object fieldValue = field.get(object);
201                         builder.append(fieldValue);
202                     } catch (final IllegalAccessException e) {
203                         // this can't happen. Would get a Security exception instead
204                         // throw a runtime exception in case the impossible happens.
205                         throw new InternalError("Unexpected IllegalAccessException");
206                     }
207                 }
208             }
209         } finally {
210             unregister(object);
211         }
212     }
213 
214     /**
215      * <p>
216      * Uses reflection to build a valid hash code from the fields of {@code object}.
217      * </p>
218      *
219      * <p>
220      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
221      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
222      * also not as efficient as testing explicitly.
223      * </p>
224      *
225      * <p>
226      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
227      * <code>Object</code>.
228      * </p>
229      *
230      * <p>
231      * Static fields will not be tested. Superclass fields will be included.
232      * </p>
233      *
234      * <p>
235      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
236      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
237      * </p>
238      *
239      * @param initialNonZeroOddNumber
240      *            a non-zero, odd number used as the initial value. This will be the returned
241      *            value if no fields are found to include in the hash code
242      * @param multiplierNonZeroOddNumber
243      *            a non-zero, odd number used as the multiplier
244      * @param object
245      *            the Object to create a <code>hashCode</code> for
246      * @return int hash code
247      * @throws IllegalArgumentException
248      *             if the Object is <code>null</code>
249      * @throws IllegalArgumentException
250      *             if the number is zero or even
251      *
252      * @see HashCodeExclude
253      */
254     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
255         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
256     }
257 
258     /**
259      * <p>
260      * Uses reflection to build a valid hash code from the fields of {@code object}.
261      * </p>
262      *
263      * <p>
264      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
265      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
266      * also not as efficient as testing explicitly.
267      * </p>
268      *
269      * <p>
270      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
271      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
272      * </p>
273      *
274      * <p>
275      * Static fields will not be tested. Superclass fields will be included.
276      * </p>
277      *
278      * <p>
279      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
280      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
281      * </p>
282      *
283      * @param initialNonZeroOddNumber
284      *            a non-zero, odd number used as the initial value. This will be the returned
285      *            value if no fields are found to include in the hash code
286      * @param multiplierNonZeroOddNumber
287      *            a non-zero, odd number used as the multiplier
288      * @param object
289      *            the Object to create a <code>hashCode</code> for
290      * @param testTransients
291      *            whether to include transient fields
292      * @return int hash code
293      * @throws IllegalArgumentException
294      *             if the Object is <code>null</code>
295      * @throws IllegalArgumentException
296      *             if the number is zero or even
297      *
298      * @see HashCodeExclude
299      */
300     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
301             final boolean testTransients) {
302         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
303     }
304 
305     /**
306      * <p>
307      * Uses reflection to build a valid hash code from the fields of {@code object}.
308      * </p>
309      *
310      * <p>
311      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
312      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
313      * also not as efficient as testing explicitly.
314      * </p>
315      *
316      * <p>
317      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
318      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
319      * </p>
320      *
321      * <p>
322      * Static fields will not be included. Superclass fields will be included up to and including the specified
323      * superclass. A null superclass is treated as java.lang.Object.
324      * </p>
325      *
326      * <p>
327      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
328      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
329      * </p>
330      *
331      * @param <T>
332      *            the type of the object involved
333      * @param initialNonZeroOddNumber
334      *            a non-zero, odd number used as the initial value. This will be the returned
335      *            value if no fields are found to include in the hash code
336      * @param multiplierNonZeroOddNumber
337      *            a non-zero, odd number used as the multiplier
338      * @param object
339      *            the Object to create a <code>hashCode</code> for
340      * @param testTransients
341      *            whether to include transient fields
342      * @param reflectUpToClass
343      *            the superclass to reflect up to (inclusive), may be <code>null</code>
344      * @param excludeFields
345      *            array of field names to exclude from use in calculation of hash code
346      * @return int hash code
347      * @throws IllegalArgumentException
348      *             if the Object is <code>null</code>
349      * @throws IllegalArgumentException
350      *             if the number is zero or even
351      *
352      * @see HashCodeExclude
353      * @since 2.0
354      */
355     public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
356             final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
357         Validate.isTrue(object != null, "The object to build a hash code for must not be null");
358         final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
359         Class<?> clazz = object.getClass();
360         reflectionAppend(object, clazz, builder, testTransients, excludeFields);
361         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
362             clazz = clazz.getSuperclass();
363             reflectionAppend(object, clazz, builder, testTransients, excludeFields);
364         }
365         return builder.toHashCode();
366     }
367 
368     /**
369      * <p>
370      * Uses reflection to build a valid hash code from the fields of {@code object}.
371      * </p>
372      *
373      * <p>
374      * This constructor uses two hard coded choices for the constants needed to build a hash code.
375      * </p>
376      *
377      * <p>
378      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
379      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
380      * also not as efficient as testing explicitly.
381      * </p>
382      *
383      * <P>
384      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
385      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
386      * </p>
387      *
388      * <p>
389      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
390      * in the hash code, the result of this method will be constant.
391      * </p>
392      *
393      * @param object
394      *            the Object to create a <code>hashCode</code> for
395      * @param testTransients
396      *            whether to include transient fields
397      * @return int hash code
398      * @throws IllegalArgumentException
399      *             if the object is <code>null</code>
400      *
401      * @see HashCodeExclude
402      */
403     public static int reflectionHashCode(final Object object, final boolean testTransients) {
404         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
405                 testTransients, null);
406     }
407 
408     /**
409      * <p>
410      * Uses reflection to build a valid hash code from the fields of {@code object}.
411      * </p>
412      *
413      * <p>
414      * This constructor uses two hard coded choices for the constants needed to build a hash code.
415      * </p>
416      *
417      * <p>
418      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
419      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
420      * also not as efficient as testing explicitly.
421      * </p>
422      *
423      * <p>
424      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
425      * <code>Object</code>.
426      * </p>
427      *
428      * <p>
429      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
430      * in the hash code, the result of this method will be constant.
431      * </p>
432      *
433      * @param object
434      *            the Object to create a <code>hashCode</code> for
435      * @param excludeFields
436      *            Collection of String field names to exclude from use in calculation of hash code
437      * @return int hash code
438      * @throws IllegalArgumentException
439      *             if the object is <code>null</code>
440      *
441      * @see HashCodeExclude
442      */
443     public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
444         return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
445     }
446 
447     // -------------------------------------------------------------------------
448 
449     /**
450      * <p>
451      * Uses reflection to build a valid hash code from the fields of {@code object}.
452      * </p>
453      *
454      * <p>
455      * This constructor uses two hard coded choices for the constants needed to build a hash code.
456      * </p>
457      *
458      * <p>
459      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
460      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
461      * also not as efficient as testing explicitly.
462      * </p>
463      *
464      * <p>
465      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
466      * <code>Object</code>.
467      * </p>
468      *
469      * <p>
470      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
471      * in the hash code, the result of this method will be constant.
472      * </p>
473      *
474      * @param object
475      *            the Object to create a <code>hashCode</code> for
476      * @param excludeFields
477      *            array of field names to exclude from use in calculation of hash code
478      * @return int hash code
479      * @throws IllegalArgumentException
480      *             if the object is <code>null</code>
481      *
482      * @see HashCodeExclude
483      */
484     public static int reflectionHashCode(final Object object, final String... excludeFields) {
485         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
486                 null, excludeFields);
487     }
488 
489     /**
490      * <p>
491      * Registers the given object. Used by the reflection methods to avoid infinite loops.
492      * </p>
493      *
494      * @param value
495      *            The object to register.
496      */
497     private static void register(final Object value) {
498         Set<IDKey> registry = getRegistry();
499         if (registry == null) {
500             registry = new HashSet<>();
501             REGISTRY.set(registry);
502         }
503         registry.add(new IDKey(value));
504     }
505 
506     /**
507      * <p>
508      * Unregisters the given object.
509      * </p>
510      *
511      * <p>
512      * Used by the reflection methods to avoid infinite loops.
513      *
514      * @param value
515      *            The object to unregister.
516      * @since 2.3
517      */
518     private static void unregister(final Object value) {
519         final Set<IDKey> registry = getRegistry();
520         if (registry != null) {
521             registry.remove(new IDKey(value));
522             if (registry.isEmpty()) {
523                 REGISTRY.remove();
524             }
525         }
526     }
527 
528     /**
529      * Constant to use in building the hashCode.
530      */
531     private final int iConstant;
532 
533     /**
534      * Running total of the hashCode.
535      */
536     private int iTotal = 0;
537 
538     /**
539      * <p>
540      * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>.
541      * </p>
542      */
543     public HashCodeBuilder() {
544         iConstant = 37;
545         iTotal = 17;
546     }
547 
548     /**
549      * <p>
550      * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
551      * however this is not vital.
552      * </p>
553      *
554      * <p>
555      * Prime numbers are preferred, especially for the multiplier.
556      * </p>
557      *
558      * @param initialOddNumber
559      *            an odd number used as the initial value
560      * @param multiplierOddNumber
561      *            an odd number used as the multiplier
562      * @throws IllegalArgumentException
563      *             if the number is even
564      */
565     public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
566         Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
567         Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
568         iConstant = multiplierOddNumber;
569         iTotal = initialOddNumber;
570     }
571 
572     /**
573      * <p>
574      * Append a <code>hashCode</code> for a <code>boolean</code>.
575      * </p>
576      * <p>
577      * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
578      * </p>
579      * <p>
580      * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
581      * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
582      * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
583      * that represent <code>false</code>.
584      * </p>
585      * <p>
586      * This is in accordance with the <i>Effective Java</i> design.
587      * </p>
588      *
589      * @param value
590      *            the boolean to add to the <code>hashCode</code>
591      * @return this
592      */
593     public HashCodeBuilder append(final boolean value) {
594         iTotal = iTotal * iConstant + (value ? 0 : 1);
595         return this;
596     }
597 
598     /**
599      * <p>
600      * Append a <code>hashCode</code> for a <code>boolean</code> array.
601      * </p>
602      *
603      * @param array
604      *            the array to add to the <code>hashCode</code>
605      * @return this
606      */
607     public HashCodeBuilder append(final boolean[] array) {
608         if (array == null) {
609             iTotal = iTotal * iConstant;
610         } else {
611             for (final boolean element : array) {
612                 append(element);
613             }
614         }
615         return this;
616     }
617 
618     // -------------------------------------------------------------------------
619 
620     /**
621      * <p>
622      * Append a <code>hashCode</code> for a <code>byte</code>.
623      * </p>
624      *
625      * @param value
626      *            the byte to add to the <code>hashCode</code>
627      * @return this
628      */
629     public HashCodeBuilder append(final byte value) {
630         iTotal = iTotal * iConstant + value;
631         return this;
632     }
633 
634     // -------------------------------------------------------------------------
635 
636     /**
637      * <p>
638      * Append a <code>hashCode</code> for a <code>byte</code> array.
639      * </p>
640      *
641      * @param array
642      *            the array to add to the <code>hashCode</code>
643      * @return this
644      */
645     public HashCodeBuilder append(final byte[] array) {
646         if (array == null) {
647             iTotal = iTotal * iConstant;
648         } else {
649             for (final byte element : array) {
650                 append(element);
651             }
652         }
653         return this;
654     }
655 
656     /**
657      * <p>
658      * Append a <code>hashCode</code> for a <code>char</code>.
659      * </p>
660      *
661      * @param value
662      *            the char to add to the <code>hashCode</code>
663      * @return this
664      */
665     public HashCodeBuilder append(final char value) {
666         iTotal = iTotal * iConstant + value;
667         return this;
668     }
669 
670     /**
671      * <p>
672      * Append a <code>hashCode</code> for a <code>char</code> array.
673      * </p>
674      *
675      * @param array
676      *            the array to add to the <code>hashCode</code>
677      * @return this
678      */
679     public HashCodeBuilder append(final char[] array) {
680         if (array == null) {
681             iTotal = iTotal * iConstant;
682         } else {
683             for (final char element : array) {
684                 append(element);
685             }
686         }
687         return this;
688     }
689 
690     /**
691      * <p>
692      * Append a <code>hashCode</code> for a <code>double</code>.
693      * </p>
694      *
695      * @param value
696      *            the double to add to the <code>hashCode</code>
697      * @return this
698      */
699     public HashCodeBuilder append(final double value) {
700         return append(Double.doubleToLongBits(value));
701     }
702 
703     /**
704      * <p>
705      * Append a <code>hashCode</code> for a <code>double</code> array.
706      * </p>
707      *
708      * @param array
709      *            the array to add to the <code>hashCode</code>
710      * @return this
711      */
712     public HashCodeBuilder append(final double[] array) {
713         if (array == null) {
714             iTotal = iTotal * iConstant;
715         } else {
716             for (final double element : array) {
717                 append(element);
718             }
719         }
720         return this;
721     }
722 
723     /**
724      * <p>
725      * Append a <code>hashCode</code> for a <code>float</code>.
726      * </p>
727      *
728      * @param value
729      *            the float to add to the <code>hashCode</code>
730      * @return this
731      */
732     public HashCodeBuilder append(final float value) {
733         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
734         return this;
735     }
736 
737     /**
738      * <p>
739      * Append a <code>hashCode</code> for a <code>float</code> array.
740      * </p>
741      *
742      * @param array
743      *            the array to add to the <code>hashCode</code>
744      * @return this
745      */
746     public HashCodeBuilder append(final float[] array) {
747         if (array == null) {
748             iTotal = iTotal * iConstant;
749         } else {
750             for (final float element : array) {
751                 append(element);
752             }
753         }
754         return this;
755     }
756 
757     /**
758      * <p>
759      * Append a <code>hashCode</code> for an <code>int</code>.
760      * </p>
761      *
762      * @param value
763      *            the int to add to the <code>hashCode</code>
764      * @return this
765      */
766     public HashCodeBuilder append(final int value) {
767         iTotal = iTotal * iConstant + value;
768         return this;
769     }
770 
771     /**
772      * <p>
773      * Append a <code>hashCode</code> for an <code>int</code> array.
774      * </p>
775      *
776      * @param array
777      *            the array to add to the <code>hashCode</code>
778      * @return this
779      */
780     public HashCodeBuilder append(final int[] array) {
781         if (array == null) {
782             iTotal = iTotal * iConstant;
783         } else {
784             for (final int element : array) {
785                 append(element);
786             }
787         }
788         return this;
789     }
790 
791     /**
792      * <p>
793      * Append a <code>hashCode</code> for a <code>long</code>.
794      * </p>
795      *
796      * @param value
797      *            the long to add to the <code>hashCode</code>
798      * @return this
799      */
800     // NOTE: This method uses >> and not >>> as Effective Java and
801     //       Long.hashCode do. Ideally we should switch to >>> at
802     //       some stage. There are backwards compat issues, so
803     //       that will have to wait for the time being. cf LANG-342.
804     public HashCodeBuilder append(final long value) {
805         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
806         return this;
807     }
808 
809     /**
810      * <p>
811      * Append a <code>hashCode</code> for a <code>long</code> array.
812      * </p>
813      *
814      * @param array
815      *            the array to add to the <code>hashCode</code>
816      * @return this
817      */
818     public HashCodeBuilder append(final long[] array) {
819         if (array == null) {
820             iTotal = iTotal * iConstant;
821         } else {
822             for (final long element : array) {
823                 append(element);
824             }
825         }
826         return this;
827     }
828 
829     /**
830      * <p>
831      * Append a <code>hashCode</code> for an <code>Object</code>.
832      * </p>
833      *
834      * @param object
835      *            the Object to add to the <code>hashCode</code>
836      * @return this
837      */
838     public HashCodeBuilder append(final Object object) {
839         if (object == null) {
840             iTotal = iTotal * iConstant;
841 
842         } else {
843             if (object.getClass().isArray()) {
844                 // factor out array case in order to keep method small enough
845                 // to be inlined
846                 appendArray(object);
847             } else {
848                 iTotal = iTotal * iConstant + object.hashCode();
849             }
850         }
851         return this;
852     }
853 
854     /**
855      * <p>
856      * Append a <code>hashCode</code> for an array.
857      * </p>
858      *
859      * @param object
860      *            the array to add to the <code>hashCode</code>
861      */
862     private void appendArray(final Object object) {
863         // 'Switch' on type of array, to dispatch to the correct handler
864         // This handles multi dimensional arrays
865         if (object instanceof long[]) {
866             append((long[]) object);
867         } else if (object instanceof int[]) {
868             append((int[]) object);
869         } else if (object instanceof short[]) {
870             append((short[]) object);
871         } else if (object instanceof char[]) {
872             append((char[]) object);
873         } else if (object instanceof byte[]) {
874             append((byte[]) object);
875         } else if (object instanceof double[]) {
876             append((double[]) object);
877         } else if (object instanceof float[]) {
878             append((float[]) object);
879         } else if (object instanceof boolean[]) {
880             append((boolean[]) object);
881         } else {
882             // Not an array of primitives
883             append((Object[]) object);
884         }
885     }
886 
887     /**
888      * <p>
889      * Append a <code>hashCode</code> for an <code>Object</code> array.
890      * </p>
891      *
892      * @param array
893      *            the array to add to the <code>hashCode</code>
894      * @return this
895      */
896     public HashCodeBuilder append(final Object[] array) {
897         if (array == null) {
898             iTotal = iTotal * iConstant;
899         } else {
900             for (final Object element : array) {
901                 append(element);
902             }
903         }
904         return this;
905     }
906 
907     /**
908      * <p>
909      * Append a <code>hashCode</code> for a <code>short</code>.
910      * </p>
911      *
912      * @param value
913      *            the short to add to the <code>hashCode</code>
914      * @return this
915      */
916     public HashCodeBuilder append(final short value) {
917         iTotal = iTotal * iConstant + value;
918         return this;
919     }
920 
921     /**
922      * <p>
923      * Append a <code>hashCode</code> for a <code>short</code> array.
924      * </p>
925      *
926      * @param array
927      *            the array to add to the <code>hashCode</code>
928      * @return this
929      */
930     public HashCodeBuilder append(final short[] array) {
931         if (array == null) {
932             iTotal = iTotal * iConstant;
933         } else {
934             for (final short element : array) {
935                 append(element);
936             }
937         }
938         return this;
939     }
940 
941     /**
942      * <p>
943      * Adds the result of super.hashCode() to this builder.
944      * </p>
945      *
946      * @param superHashCode
947      *            the result of calling <code>super.hashCode()</code>
948      * @return this HashCodeBuilder, used to chain calls.
949      * @since 2.0
950      */
951     public HashCodeBuilder appendSuper(final int superHashCode) {
952         iTotal = iTotal * iConstant + superHashCode;
953         return this;
954     }
955 
956     /**
957      * <p>
958      * Return the computed <code>hashCode</code>.
959      * </p>
960      *
961      * @return <code>hashCode</code> based on the fields appended
962      */
963     public int toHashCode() {
964         return iTotal;
965     }
966 
967     /**
968      * Returns the computed <code>hashCode</code>.
969      *
970      * @return <code>hashCode</code> based on the fields appended
971      *
972      * @since 3.0
973      */
974     @Override
975     public Integer build() {
976         return Integer.valueOf(toHashCode());
977     }
978 
979     /**
980      * <p>
981      * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
982      * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
983      * HashCodeBuilder itself is.</p>
984      *
985      * @return <code>hashCode</code> based on the fields appended
986      * @since 2.5
987      */
988     @Override
989     public int hashCode() {
990         return toHashCode();
991     }
992 
993 }