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