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