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 }