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 }