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