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 = ThreadLocal.withInitial(HashSet::new);
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         getRegistry().add(new IDKey(value));
471     }
472 
473     /**
474      * Unregisters the given object.
475      *
476      * <p>
477      * Used by the reflection methods to avoid infinite loops.
478      * </p>
479      *
480      * @param value
481      *            The object to unregister.
482      * @since 2.3
483      */
484     private static void unregister(final Object value) {
485         final Set<IDKey> registry = getRegistry();
486         registry.remove(new IDKey(value));
487         if (registry.isEmpty()) {
488             REGISTRY.remove();
489         }
490     }
491 
492     /**
493      * Constant to use in building the hashCode.
494      */
495     private final int iConstant;
496 
497     /**
498      * Running total of the hashCode.
499      */
500     private int iTotal;
501 
502     /**
503      * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
504      */
505     public HashCodeBuilder() {
506         iConstant = 37;
507         iTotal = 17;
508     }
509 
510     /**
511      * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
512      * however this is not vital.
513      *
514      * <p>
515      * Prime numbers are preferred, especially for the multiplier.
516      * </p>
517      *
518      * @param initialOddNumber
519      *            an odd number used as the initial value
520      * @param multiplierOddNumber
521      *            an odd number used as the multiplier
522      * @throws IllegalArgumentException
523      *             if the number is even
524      */
525     public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
526         Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
527         Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
528         iConstant = multiplierOddNumber;
529         iTotal = initialOddNumber;
530     }
531 
532     /**
533      * Append a {@code hashCode} for a {@code boolean}.
534      *
535      * <p>
536      * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
537      * </p>
538      * <p>
539      * This is in contrast to the standard {@link Boolean#hashCode()} handling, which computes
540      * a {@code hashCode} value of {@code 1231} for {@link Boolean} instances
541      * that represent {@code true} or {@code 1237} for {@link Boolean} instances
542      * that represent {@code false}.
543      * </p>
544      * <p>
545      * This is in accordance with the <em>Effective Java</em> design.
546      * </p>
547      *
548      * @param value
549      *            the boolean to add to the {@code hashCode}
550      * @return {@code this} instance.
551      */
552     public HashCodeBuilder append(final boolean value) {
553         iTotal = iTotal * iConstant + (value ? 0 : 1);
554         return this;
555     }
556 
557     /**
558      * Append a {@code hashCode} for a {@code boolean} array.
559      *
560      * @param array
561      *            the array to add to the {@code hashCode}
562      * @return {@code this} instance.
563      */
564     public HashCodeBuilder append(final boolean[] array) {
565         if (array == null) {
566             iTotal = iTotal * iConstant;
567         } else {
568             for (final boolean element : array) {
569                 append(element);
570             }
571         }
572         return this;
573     }
574 
575     /**
576      * Append a {@code hashCode} for a {@code byte}.
577      *
578      * @param value
579      *            the byte to add to the {@code hashCode}
580      * @return {@code this} instance.
581      */
582     public HashCodeBuilder append(final byte value) {
583         iTotal = iTotal * iConstant + value;
584         return this;
585     }
586 
587     /**
588      * Append a {@code hashCode} for a {@code byte} array.
589      *
590      * @param array
591      *            the array to add to the {@code hashCode}
592      * @return {@code this} instance.
593      */
594     public HashCodeBuilder append(final byte[] array) {
595         if (array == null) {
596             iTotal = iTotal * iConstant;
597         } else {
598             for (final byte element : array) {
599                 append(element);
600             }
601         }
602         return this;
603     }
604 
605     /**
606      * Append a {@code hashCode} for a {@code char}.
607      *
608      * @param value
609      *            the char to add to the {@code hashCode}
610      * @return {@code this} instance.
611      */
612     public HashCodeBuilder append(final char value) {
613         iTotal = iTotal * iConstant + value;
614         return this;
615     }
616 
617     /**
618      * Append a {@code hashCode} for a {@code char} array.
619      *
620      * @param array
621      *            the array to add to the {@code hashCode}
622      * @return {@code this} instance.
623      */
624     public HashCodeBuilder append(final char[] array) {
625         if (array == null) {
626             iTotal = iTotal * iConstant;
627         } else {
628             for (final char element : array) {
629                 append(element);
630             }
631         }
632         return this;
633     }
634 
635     /**
636      * Append a {@code hashCode} for a {@code double}.
637      *
638      * @param value
639      *            the double to add to the {@code hashCode}
640      * @return {@code this} instance.
641      */
642     public HashCodeBuilder append(final double value) {
643         return append(Double.doubleToLongBits(value));
644     }
645 
646     /**
647      * Append a {@code hashCode} for a {@code double} array.
648      *
649      * @param array
650      *            the array to add to the {@code hashCode}
651      * @return {@code this} instance.
652      */
653     public HashCodeBuilder append(final double[] array) {
654         if (array == null) {
655             iTotal = iTotal * iConstant;
656         } else {
657             for (final double element : array) {
658                 append(element);
659             }
660         }
661         return this;
662     }
663 
664     /**
665      * Append a {@code hashCode} for a {@code float}.
666      *
667      * @param value
668      *            the float to add to the {@code hashCode}
669      * @return {@code this} instance.
670      */
671     public HashCodeBuilder append(final float value) {
672         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
673         return this;
674     }
675 
676     /**
677      * Append a {@code hashCode} for a {@code float} array.
678      *
679      * @param array
680      *            the array to add to the {@code hashCode}
681      * @return {@code this} instance.
682      */
683     public HashCodeBuilder append(final float[] array) {
684         if (array == null) {
685             iTotal = iTotal * iConstant;
686         } else {
687             for (final float element : array) {
688                 append(element);
689             }
690         }
691         return this;
692     }
693 
694     /**
695      * Append a {@code hashCode} for an {@code int}.
696      *
697      * @param value
698      *            the int to add to the {@code hashCode}
699      * @return {@code this} instance.
700      */
701     public HashCodeBuilder append(final int value) {
702         iTotal = iTotal * iConstant + value;
703         return this;
704     }
705 
706     /**
707      * Append a {@code hashCode} for an {@code int} array.
708      *
709      * @param array
710      *            the array to add to the {@code hashCode}
711      * @return {@code this} instance.
712      */
713     public HashCodeBuilder append(final int[] array) {
714         if (array == null) {
715             iTotal = iTotal * iConstant;
716         } else {
717             for (final int element : array) {
718                 append(element);
719             }
720         }
721         return this;
722     }
723 
724     /**
725      * Append a {@code hashCode} for a {@code long}.
726      *
727      * @param value
728      *            the long to add to the {@code hashCode}
729      * @return {@code this} instance.
730      */
731     // NOTE: This method uses >> and not >>> as Effective Java and
732     //       Long.hashCode do. Ideally we should switch to >>> at
733     //       some stage. There are backwards compat issues, so
734     //       that will have to wait for the time being. cf LANG-342.
735     public HashCodeBuilder append(final long value) {
736         iTotal = iTotal * iConstant + (int) (value ^ value >> 32);
737         return this;
738     }
739 
740     /**
741      * Append a {@code hashCode} for a {@code long} array.
742      *
743      * @param array
744      *            the array to add to the {@code hashCode}
745      * @return {@code this} instance.
746      */
747     public HashCodeBuilder append(final long[] array) {
748         if (array == null) {
749             iTotal = iTotal * iConstant;
750         } else {
751             for (final long element : array) {
752                 append(element);
753             }
754         }
755         return this;
756     }
757 
758     /**
759      * Append a {@code hashCode} for an {@link Object}.
760      *
761      * @param object
762      *            the Object to add to the {@code hashCode}
763      * @return {@code this} instance.
764      */
765     public HashCodeBuilder append(final Object object) {
766         if (object == null) {
767             iTotal = iTotal * iConstant;
768 
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             iTotal = iTotal * iConstant + 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             iTotal = iTotal * iConstant;
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         iTotal = iTotal * iConstant + 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             iTotal = iTotal * iConstant;
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         iTotal = iTotal * iConstant + 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 iTotal == other.iTotal;
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 iTotal;
919     }
920 
921 }