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