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 * http://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.Set; 027 028import org.apache.commons.lang3.ArraySorter; 029import org.apache.commons.lang3.ArrayUtils; 030import org.apache.commons.lang3.Validate; 031 032/** 033 * <p> 034 * Assists in implementing {@link Object#hashCode()} methods. 035 * </p> 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="http://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 * 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 * <p> 118 * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. 119 * </p> 120 * 121 * @since 2.3 122 */ 123 private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<>(); 124 125 /* 126 * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode() 127 * we are in the process of calculating. 128 * 129 * So we generate a one-to-one mapping from the original object to a new object. 130 * 131 * Now HashSet uses equals() to determine if two elements with the same hash code really 132 * are equal, so we also need to ensure that the replacement objects are only equal 133 * if the original objects are identical. 134 * 135 * The original implementation (2.4 and before) used the System.identityHashCode() 136 * method - however this is not guaranteed to generate unique ids (e.g. LANG-459) 137 * 138 * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey) 139 * to disambiguate the duplicate ids. 140 */ 141 142 /** 143 * <p> 144 * Returns the registry of objects being traversed by the reflection methods in the current thread. 145 * </p> 146 * 147 * @return Set the registry of objects being traversed 148 * @since 2.3 149 */ 150 static Set<IDKey> getRegistry() { 151 return REGISTRY.get(); 152 } 153 154 /** 155 * <p> 156 * Returns {@code true} if the registry contains the given object. Used by the reflection methods to avoid 157 * infinite loops. 158 * </p> 159 * 160 * @param value 161 * The object to lookup in the registry. 162 * @return boolean {@code true} if the registry contains the given object. 163 * @since 2.3 164 */ 165 static boolean isRegistered(final Object value) { 166 final Set<IDKey> registry = getRegistry(); 167 return registry != null && registry.contains(new IDKey(value)); 168 } 169 170 /** 171 * <p> 172 * Appends the fields and values defined by the given object of the given {@code Class}. 173 * </p> 174 * 175 * @param object 176 * the object to append details of 177 * @param clazz 178 * the class to append details of 179 * @param builder 180 * the builder to append to 181 * @param useTransients 182 * whether to use transient fields 183 * @param excludeFields 184 * Collection of String field names to exclude from use in calculation of hash code 185 */ 186 private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients, 187 final String[] excludeFields) { 188 if (isRegistered(object)) { 189 return; 190 } 191 try { 192 register(object); 193 // The elements in the returned array are not sorted and are not in any particular order. 194 final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName)); 195 AccessibleObject.setAccessible(fields, true); 196 for (final Field field : fields) { 197 if (!ArrayUtils.contains(excludeFields, field.getName()) 198 && !field.getName().contains("$") 199 && (useTransients || !Modifier.isTransient(field.getModifiers())) 200 && !Modifier.isStatic(field.getModifiers()) 201 && !field.isAnnotationPresent(HashCodeExclude.class)) { 202 try { 203 final Object fieldValue = field.get(object); 204 builder.append(fieldValue); 205 } catch (final IllegalAccessException e) { 206 // this can't happen. Would get a Security exception instead 207 // throw a runtime exception in case the impossible happens. 208 throw new InternalError("Unexpected IllegalAccessException"); 209 } 210 } 211 } 212 } finally { 213 unregister(object); 214 } 215 } 216 217 /** 218 * <p> 219 * Uses reflection to build a valid hash code from the fields of {@code object}. 220 * </p> 221 * 222 * <p> 223 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 224 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 225 * also not as efficient as testing explicitly. 226 * </p> 227 * 228 * <p> 229 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 230 * {@code Object}. 231 * </p> 232 * 233 * <p> 234 * Static fields will not be tested. Superclass fields will be included. 235 * </p> 236 * 237 * <p> 238 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 239 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 240 * </p> 241 * 242 * @param initialNonZeroOddNumber 243 * a non-zero, odd number used as the initial value. This will be the returned 244 * value if no fields are found to include in the hash code 245 * @param multiplierNonZeroOddNumber 246 * a non-zero, odd number used as the multiplier 247 * @param object 248 * the Object to create a {@code hashCode} for 249 * @return int hash code 250 * @throws IllegalArgumentException 251 * if the Object is {@code null} 252 * @throws IllegalArgumentException 253 * if the number is zero or even 254 * 255 * @see HashCodeExclude 256 */ 257 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) { 258 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null); 259 } 260 261 /** 262 * <p> 263 * Uses reflection to build a valid hash code from the fields of {@code object}. 264 * </p> 265 * 266 * <p> 267 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 268 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 269 * also not as efficient as testing explicitly. 270 * </p> 271 * 272 * <p> 273 * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they 274 * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}. 275 * </p> 276 * 277 * <p> 278 * Static fields will not be tested. Superclass fields will be included. 279 * </p> 280 * 281 * <p> 282 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 283 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 284 * </p> 285 * 286 * @param initialNonZeroOddNumber 287 * a non-zero, odd number used as the initial value. This will be the returned 288 * value if no fields are found to include in the hash code 289 * @param multiplierNonZeroOddNumber 290 * a non-zero, odd number used as the multiplier 291 * @param object 292 * the Object to create a {@code hashCode} for 293 * @param testTransients 294 * whether to include transient fields 295 * @return int hash code 296 * @throws IllegalArgumentException 297 * if the Object is {@code null} 298 * @throws IllegalArgumentException 299 * if the number is zero or even 300 * 301 * @see HashCodeExclude 302 */ 303 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object, 304 final boolean testTransients) { 305 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null); 306 } 307 308 /** 309 * <p> 310 * Uses reflection to build a valid hash code from the fields of {@code object}. 311 * </p> 312 * 313 * <p> 314 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 315 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 316 * also not as efficient as testing explicitly. 317 * </p> 318 * 319 * <p> 320 * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they 321 * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}. 322 * </p> 323 * 324 * <p> 325 * Static fields will not be included. Superclass fields will be included up to and including the specified 326 * superclass. A null superclass is treated as java.lang.Object. 327 * </p> 328 * 329 * <p> 330 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 331 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 332 * </p> 333 * 334 * @param <T> 335 * the type of the object involved 336 * @param initialNonZeroOddNumber 337 * a non-zero, odd number used as the initial value. This will be the returned 338 * value if no fields are found to include in the hash code 339 * @param multiplierNonZeroOddNumber 340 * a non-zero, odd number used as the multiplier 341 * @param object 342 * the Object to create a {@code hashCode} for 343 * @param testTransients 344 * whether to include transient fields 345 * @param reflectUpToClass 346 * the superclass to reflect up to (inclusive), may be {@code null} 347 * @param excludeFields 348 * array of field names to exclude from use in calculation of hash code 349 * @return int hash code 350 * @throws IllegalArgumentException 351 * if the Object is {@code null} 352 * @throws IllegalArgumentException 353 * if the number is zero or even 354 * 355 * @see HashCodeExclude 356 * @since 2.0 357 */ 358 public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object, 359 final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) { 360 Validate.notNull(object, "object"); 361 final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber); 362 Class<?> clazz = object.getClass(); 363 reflectionAppend(object, clazz, builder, testTransients, excludeFields); 364 while (clazz.getSuperclass() != null && clazz != reflectUpToClass) { 365 clazz = clazz.getSuperclass(); 366 reflectionAppend(object, clazz, builder, testTransients, excludeFields); 367 } 368 return builder.toHashCode(); 369 } 370 371 /** 372 * <p> 373 * Uses reflection to build a valid hash code from the fields of {@code object}. 374 * </p> 375 * 376 * <p> 377 * This constructor uses two hard coded choices for the constants needed to build a hash code. 378 * </p> 379 * 380 * <p> 381 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 382 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 383 * also not as efficient as testing explicitly. 384 * </p> 385 * 386 * <P> 387 * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they 388 * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}. 389 * </p> 390 * 391 * <p> 392 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 393 * in the hash code, the result of this method will be constant. 394 * </p> 395 * 396 * @param object 397 * the Object to create a {@code hashCode} for 398 * @param testTransients 399 * whether to include transient fields 400 * @return int hash code 401 * @throws IllegalArgumentException 402 * if the object is {@code null} 403 * 404 * @see HashCodeExclude 405 */ 406 public static int reflectionHashCode(final Object object, final boolean testTransients) { 407 return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, 408 testTransients, null); 409 } 410 411 /** 412 * <p> 413 * Uses reflection to build a valid hash code from the fields of {@code object}. 414 * </p> 415 * 416 * <p> 417 * This constructor uses two hard coded choices for the constants needed to build a hash code. 418 * </p> 419 * 420 * <p> 421 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 422 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 423 * also not as efficient as testing explicitly. 424 * </p> 425 * 426 * <p> 427 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 428 * {@code Object}. 429 * </p> 430 * 431 * <p> 432 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 433 * in the hash code, the result of this method will be constant. 434 * </p> 435 * 436 * @param object 437 * the Object to create a {@code hashCode} for 438 * @param excludeFields 439 * Collection of String field names to exclude from use in calculation of hash code 440 * @return int hash code 441 * @throws IllegalArgumentException 442 * if the object is {@code null} 443 * 444 * @see HashCodeExclude 445 */ 446 public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) { 447 return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields)); 448 } 449 450 // ------------------------------------------------------------------------- 451 452 /** 453 * <p> 454 * Uses reflection to build a valid hash code from the fields of {@code object}. 455 * </p> 456 * 457 * <p> 458 * This constructor uses two hard coded choices for the constants needed to build a hash code. 459 * </p> 460 * 461 * <p> 462 * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will 463 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 464 * also not as efficient as testing explicitly. 465 * </p> 466 * 467 * <p> 468 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 469 * {@code Object}. 470 * </p> 471 * 472 * <p> 473 * Static fields will not be tested. Superclass fields will be included. If no fields are found to include 474 * in the hash code, the result of this method will be constant. 475 * </p> 476 * 477 * @param object 478 * the Object to create a {@code hashCode} for 479 * @param excludeFields 480 * array of field names to exclude from use in calculation of hash code 481 * @return int hash code 482 * @throws IllegalArgumentException 483 * if the object is {@code null} 484 * 485 * @see HashCodeExclude 486 */ 487 public static int reflectionHashCode(final Object object, final String... excludeFields) { 488 return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false, 489 null, excludeFields); 490 } 491 492 /** 493 * <p> 494 * Registers the given object. Used by the reflection methods to avoid infinite loops. 495 * </p> 496 * 497 * @param value 498 * The object to register. 499 */ 500 private static void register(final Object value) { 501 Set<IDKey> registry = getRegistry(); 502 if (registry == null) { 503 registry = new HashSet<>(); 504 REGISTRY.set(registry); 505 } 506 registry.add(new IDKey(value)); 507 } 508 509 /** 510 * <p> 511 * Unregisters the given object. 512 * </p> 513 * 514 * <p> 515 * Used by the reflection methods to avoid infinite loops. 516 * 517 * @param value 518 * The object to unregister. 519 * @since 2.3 520 */ 521 private static void unregister(final Object value) { 522 final Set<IDKey> registry = getRegistry(); 523 if (registry != null) { 524 registry.remove(new IDKey(value)); 525 if (registry.isEmpty()) { 526 REGISTRY.remove(); 527 } 528 } 529 } 530 531 /** 532 * Constant to use in building the hashCode. 533 */ 534 private final int iConstant; 535 536 /** 537 * Running total of the hashCode. 538 */ 539 private int iTotal; 540 541 /** 542 * <p> 543 * Uses two hard coded choices for the constants needed to build a {@code hashCode}. 544 * </p> 545 */ 546 public HashCodeBuilder() { 547 iConstant = 37; 548 iTotal = 17; 549 } 550 551 /** 552 * <p> 553 * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class, 554 * however this is not vital. 555 * </p> 556 * 557 * <p> 558 * Prime numbers are preferred, especially for the multiplier. 559 * </p> 560 * 561 * @param initialOddNumber 562 * an odd number used as the initial value 563 * @param multiplierOddNumber 564 * an odd number used as the multiplier 565 * @throws IllegalArgumentException 566 * if the number is even 567 */ 568 public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) { 569 Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value"); 570 Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier"); 571 iConstant = multiplierOddNumber; 572 iTotal = initialOddNumber; 573 } 574 575 /** 576 * <p> 577 * Append a {@code hashCode} for a {@code boolean}. 578 * </p> 579 * <p> 580 * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}. 581 * </p> 582 * <p> 583 * This is in contrast to the standard {@code java.lang.Boolean.hashCode} handling, which computes 584 * a {@code hashCode} value of {@code 1231} for {@code java.lang.Boolean} instances 585 * that represent {@code true} or {@code 1237} for {@code java.lang.Boolean} instances 586 * that represent {@code false}. 587 * </p> 588 * <p> 589 * This is in accordance with the <i>Effective Java</i> design. 590 * </p> 591 * 592 * @param value 593 * the boolean to add to the {@code hashCode} 594 * @return this 595 */ 596 public HashCodeBuilder append(final boolean value) { 597 iTotal = iTotal * iConstant + (value ? 0 : 1); 598 return this; 599 } 600 601 /** 602 * <p> 603 * Append a {@code hashCode} for a {@code boolean} array. 604 * </p> 605 * 606 * @param array 607 * the array to add to the {@code hashCode} 608 * @return this 609 */ 610 public HashCodeBuilder append(final boolean[] array) { 611 if (array == null) { 612 iTotal = iTotal * iConstant; 613 } else { 614 for (final boolean element : array) { 615 append(element); 616 } 617 } 618 return this; 619 } 620 621 // ------------------------------------------------------------------------- 622 623 /** 624 * <p> 625 * Append a {@code hashCode} for a {@code byte}. 626 * </p> 627 * 628 * @param value 629 * the byte to add to the {@code hashCode} 630 * @return this 631 */ 632 public HashCodeBuilder append(final byte value) { 633 iTotal = iTotal * iConstant + value; 634 return this; 635 } 636 637 // ------------------------------------------------------------------------- 638 639 /** 640 * <p> 641 * Append a {@code hashCode} for a {@code byte} array. 642 * </p> 643 * 644 * @param array 645 * the array to add to the {@code hashCode} 646 * @return this 647 */ 648 public HashCodeBuilder append(final byte[] array) { 649 if (array == null) { 650 iTotal = iTotal * iConstant; 651 } else { 652 for (final byte element : array) { 653 append(element); 654 } 655 } 656 return this; 657 } 658 659 /** 660 * <p> 661 * Append a {@code hashCode} for a {@code char}. 662 * </p> 663 * 664 * @param value 665 * the char to add to the {@code hashCode} 666 * @return this 667 */ 668 public HashCodeBuilder append(final char value) { 669 iTotal = iTotal * iConstant + value; 670 return this; 671 } 672 673 /** 674 * <p> 675 * Append a {@code hashCode} for a {@code char} array. 676 * </p> 677 * 678 * @param array 679 * the array to add to the {@code hashCode} 680 * @return this 681 */ 682 public HashCodeBuilder append(final char[] array) { 683 if (array == null) { 684 iTotal = iTotal * iConstant; 685 } else { 686 for (final char element : array) { 687 append(element); 688 } 689 } 690 return this; 691 } 692 693 /** 694 * <p> 695 * Append a {@code hashCode} for a {@code double}. 696 * </p> 697 * 698 * @param value 699 * the double to add to the {@code hashCode} 700 * @return this 701 */ 702 public HashCodeBuilder append(final double value) { 703 return append(Double.doubleToLongBits(value)); 704 } 705 706 /** 707 * <p> 708 * Append a {@code hashCode} for a {@code double} array. 709 * </p> 710 * 711 * @param array 712 * the array to add to the {@code hashCode} 713 * @return this 714 */ 715 public HashCodeBuilder append(final double[] array) { 716 if (array == null) { 717 iTotal = iTotal * iConstant; 718 } else { 719 for (final double element : array) { 720 append(element); 721 } 722 } 723 return this; 724 } 725 726 /** 727 * <p> 728 * Append a {@code hashCode} for a {@code float}. 729 * </p> 730 * 731 * @param value 732 * the float to add to the {@code hashCode} 733 * @return this 734 */ 735 public HashCodeBuilder append(final float value) { 736 iTotal = iTotal * iConstant + Float.floatToIntBits(value); 737 return this; 738 } 739 740 /** 741 * <p> 742 * Append a {@code hashCode} for a {@code float} array. 743 * </p> 744 * 745 * @param array 746 * the array to add to the {@code hashCode} 747 * @return this 748 */ 749 public HashCodeBuilder append(final float[] array) { 750 if (array == null) { 751 iTotal = iTotal * iConstant; 752 } else { 753 for (final float element : array) { 754 append(element); 755 } 756 } 757 return this; 758 } 759 760 /** 761 * <p> 762 * Append a {@code hashCode} for an {@code int}. 763 * </p> 764 * 765 * @param value 766 * the int to add to the {@code hashCode} 767 * @return this 768 */ 769 public HashCodeBuilder append(final int value) { 770 iTotal = iTotal * iConstant + value; 771 return this; 772 } 773 774 /** 775 * <p> 776 * Append a {@code hashCode} for an {@code int} array. 777 * </p> 778 * 779 * @param array 780 * the array to add to the {@code hashCode} 781 * @return this 782 */ 783 public HashCodeBuilder append(final int[] array) { 784 if (array == null) { 785 iTotal = iTotal * iConstant; 786 } else { 787 for (final int element : array) { 788 append(element); 789 } 790 } 791 return this; 792 } 793 794 /** 795 * <p> 796 * Append a {@code hashCode} for a {@code long}. 797 * </p> 798 * 799 * @param value 800 * the long to add to the {@code hashCode} 801 * @return this 802 */ 803 // NOTE: This method uses >> and not >>> as Effective Java and 804 // Long.hashCode do. Ideally we should switch to >>> at 805 // some stage. There are backwards compat issues, so 806 // that will have to wait for the time being. cf LANG-342. 807 public HashCodeBuilder append(final long value) { 808 iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32))); 809 return this; 810 } 811 812 /** 813 * <p> 814 * Append a {@code hashCode} for a {@code long} array. 815 * </p> 816 * 817 * @param array 818 * the array to add to the {@code hashCode} 819 * @return this 820 */ 821 public HashCodeBuilder append(final long[] array) { 822 if (array == null) { 823 iTotal = iTotal * iConstant; 824 } else { 825 for (final long element : array) { 826 append(element); 827 } 828 } 829 return this; 830 } 831 832 /** 833 * <p> 834 * Append a {@code hashCode} for an {@code Object}. 835 * </p> 836 * 837 * @param object 838 * the Object to add to the {@code hashCode} 839 * @return this 840 */ 841 public HashCodeBuilder append(final Object object) { 842 if (object == null) { 843 iTotal = iTotal * iConstant; 844 845 } else if (object.getClass().isArray()) { 846 // factor out array case in order to keep method small enough 847 // to be inlined 848 appendArray(object); 849 } else { 850 iTotal = iTotal * iConstant + object.hashCode(); 851 } 852 return this; 853 } 854 855 /** 856 * <p> 857 * Append a {@code hashCode} for an array. 858 * </p> 859 * 860 * @param object 861 * the array to add to the {@code hashCode} 862 */ 863 private void appendArray(final Object object) { 864 // 'Switch' on type of array, to dispatch to the correct handler 865 // This handles multi dimensional arrays 866 if (object instanceof long[]) { 867 append((long[]) object); 868 } else if (object instanceof int[]) { 869 append((int[]) object); 870 } else if (object instanceof short[]) { 871 append((short[]) object); 872 } else if (object instanceof char[]) { 873 append((char[]) object); 874 } else if (object instanceof byte[]) { 875 append((byte[]) object); 876 } else if (object instanceof double[]) { 877 append((double[]) object); 878 } else if (object instanceof float[]) { 879 append((float[]) object); 880 } else if (object instanceof boolean[]) { 881 append((boolean[]) object); 882 } else { 883 // Not an array of primitives 884 append((Object[]) object); 885 } 886 } 887 888 /** 889 * <p> 890 * Append a {@code hashCode} for an {@code Object} array. 891 * </p> 892 * 893 * @param array 894 * the array to add to the {@code hashCode} 895 * @return this 896 */ 897 public HashCodeBuilder append(final Object[] array) { 898 if (array == null) { 899 iTotal = iTotal * iConstant; 900 } else { 901 for (final Object element : array) { 902 append(element); 903 } 904 } 905 return this; 906 } 907 908 /** 909 * <p> 910 * Append a {@code hashCode} for a {@code short}. 911 * </p> 912 * 913 * @param value 914 * the short to add to the {@code hashCode} 915 * @return this 916 */ 917 public HashCodeBuilder append(final short value) { 918 iTotal = iTotal * iConstant + value; 919 return this; 920 } 921 922 /** 923 * <p> 924 * Append a {@code hashCode} for a {@code short} array. 925 * </p> 926 * 927 * @param array 928 * the array to add to the {@code hashCode} 929 * @return this 930 */ 931 public HashCodeBuilder append(final short[] array) { 932 if (array == null) { 933 iTotal = iTotal * iConstant; 934 } else { 935 for (final short element : array) { 936 append(element); 937 } 938 } 939 return this; 940 } 941 942 /** 943 * <p> 944 * Adds the result of super.hashCode() to this builder. 945 * </p> 946 * 947 * @param superHashCode 948 * the result of calling {@code super.hashCode()} 949 * @return this HashCodeBuilder, used to chain calls. 950 * @since 2.0 951 */ 952 public HashCodeBuilder appendSuper(final int superHashCode) { 953 iTotal = iTotal * iConstant + superHashCode; 954 return this; 955 } 956 957 /** 958 * <p> 959 * Returns the computed {@code hashCode}. 960 * </p> 961 * 962 * @return {@code hashCode} based on the fields appended 963 */ 964 public int toHashCode() { 965 return iTotal; 966 } 967 968 /** 969 * Returns the computed {@code hashCode}. 970 * 971 * @return {@code hashCode} based on the fields appended 972 * 973 * @since 3.0 974 */ 975 @Override 976 public Integer build() { 977 return Integer.valueOf(toHashCode()); 978 } 979 980 /** 981 * <p> 982 * The computed {@code hashCode} from toHashCode() is returned due to the likelihood 983 * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for 984 * HashCodeBuilder itself is.</p> 985 * 986 * @return {@code hashCode} based on the fields appended 987 * @since 2.5 988 */ 989 @Override 990 public int hashCode() { 991 return toHashCode(); 992 } 993 994}