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