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