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