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.HashSet; 025import java.util.Set; 026 027import org.apache.commons.lang3.ArrayUtils; 028import org.apache.commons.lang3.Validate; 029 030/** 031 * <p> 032 * Assists in implementing {@link Object#hashCode()} methods. 033 * </p> 034 * 035 * <p> 036 * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in 037 * the book <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a 038 * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process. 039 * </p> 040 * 041 * <p> 042 * The following is the approach taken. When appending a data field, the current total is multiplied by the 043 * multiplier then a relevant value 044 * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then 045 * appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45. 046 * </p> 047 * 048 * <p> 049 * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be 050 * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code> 051 * method. 052 * </p> 053 * 054 * <p> 055 * To use this class write code as follows: 056 * </p> 057 * 058 * <pre> 059 * public class Person { 060 * String name; 061 * int age; 062 * boolean smoker; 063 * ... 064 * 065 * public int hashCode() { 066 * // you pick a hard-coded, randomly chosen, non-zero, odd number 067 * // ideally different for each class 068 * return new HashCodeBuilder(17, 37). 069 * append(name). 070 * append(age). 071 * append(smoker). 072 * toHashCode(); 073 * } 074 * } 075 * </pre> 076 * 077 * <p> 078 * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}. 079 * </p> 080 * 081 * <p> 082 * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are 083 * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code> 084 * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions 085 * are set up correctly. It is also slower than testing explicitly. 086 * </p> 087 * 088 * <p> 089 * A typical invocation for this method would look like: 090 * </p> 091 * 092 * <pre> 093 * public int hashCode() { 094 * return HashCodeBuilder.reflectionHashCode(this); 095 * } 096 * </pre> 097 * 098 * <p>The {@link HashCodeExclude} annotation can be used to exclude fields from being 099 * used by the <code>reflectionHashCode</code> methods.</p> 100 * 101 * @since 1.0 102 */ 103public class HashCodeBuilder implements Builder<Integer> { 104 /** 105 * The default initial value to use in reflection hash code building. 106 */ 107 private static final int DEFAULT_INITIAL_VALUE = 17; 108 109 /** 110 * The default multiplier value to use in reflection hash code building. 111 */ 112 private static final int DEFAULT_MULTIPLIER_VALUE = 37; 113 114 /** 115 * <p> 116 * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. 117 * </p> 118 * 119 * @since 2.3 120 */ 121 private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<Set<IDKey>>(); 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 hashcode 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 * <p> 142 * Returns the registry of objects being traversed by the reflection methods in the current thread. 143 * </p> 144 * 145 * @return Set the registry of objects being traversed 146 * @since 2.3 147 */ 148 static Set<IDKey> getRegistry() { 149 return REGISTRY.get(); 150 } 151 152 /** 153 * <p> 154 * Returns <code>true</code> if the registry contains the given object. Used by the reflection methods to avoid 155 * infinite loops. 156 * </p> 157 * 158 * @param value 159 * The object to lookup in the registry. 160 * @return boolean <code>true</code> if the registry contains the given object. 161 * @since 2.3 162 */ 163 static boolean isRegistered(final Object value) { 164 final Set<IDKey> registry = getRegistry(); 165 return registry != null && registry.contains(new IDKey(value)); 166 } 167 168 /** 169 * <p> 170 * Appends the fields and values defined by the given object of the given <code>Class</code>. 171 * </p> 172 * 173 * @param object 174 * the object to append details of 175 * @param clazz 176 * the class to append details of 177 * @param builder 178 * the builder to append to 179 * @param useTransients 180 * whether to use transient fields 181 * @param excludeFields 182 * Collection of String field names to exclude from use in calculation of hash code 183 */ 184 private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients, 185 final String[] excludeFields) { 186 if (isRegistered(object)) { 187 return; 188 } 189 try { 190 register(object); 191 final Field[] fields = clazz.getDeclaredFields(); 192 AccessibleObject.setAccessible(fields, true); 193 for (final Field field : fields) { 194 if (!ArrayUtils.contains(excludeFields, field.getName()) 195 && !field.getName().contains("$") 196 && (useTransients || !Modifier.isTransient(field.getModifiers())) 197 && !Modifier.isStatic(field.getModifiers()) 198 && !field.isAnnotationPresent(HashCodeExclude.class)) { 199 try { 200 final Object fieldValue = field.get(object); 201 builder.append(fieldValue); 202 } catch (final IllegalAccessException e) { 203 // this can't happen. Would get a Security exception instead 204 // throw a runtime exception in case the impossible happens. 205 throw new InternalError("Unexpected IllegalAccessException"); 206 } 207 } 208 } 209 } finally { 210 unregister(object); 211 } 212 } 213 214 /** 215 * <p> 216 * Uses reflection to build a valid hash code from the fields of {@code object}. 217 * </p> 218 * 219 * <p> 220 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will 221 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 222 * also not as efficient as testing explicitly. 223 * </p> 224 * 225 * <p> 226 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the 227 * <code>Object</code>. 228 * </p> 229 * 230 * <p> 231 * Static fields will not be tested. Superclass fields will be included. 232 * </p> 233 * 234 * <p> 235 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 236 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 237 * </p> 238 * 239 * @param initialNonZeroOddNumber 240 * a non-zero, odd number used as the initial value. This will be the returned 241 * value if no fields are found to include in the hash code 242 * @param multiplierNonZeroOddNumber 243 * a non-zero, odd number used as the multiplier 244 * @param object 245 * the Object to create a <code>hashCode</code> for 246 * @return int hash code 247 * @throws IllegalArgumentException 248 * if the Object is <code>null</code> 249 * @throws IllegalArgumentException 250 * if the number is zero or even 251 * 252 * @see HashCodeExclude 253 */ 254 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) { 255 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null); 256 } 257 258 /** 259 * <p> 260 * Uses reflection to build a valid hash code from the fields of {@code object}. 261 * </p> 262 * 263 * <p> 264 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will 265 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 266 * also not as efficient as testing explicitly. 267 * </p> 268 * 269 * <p> 270 * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they 271 * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>. 272 * </p> 273 * 274 * <p> 275 * Static fields will not be tested. Superclass fields will be included. 276 * </p> 277 * 278 * <p> 279 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 280 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 281 * </p> 282 * 283 * @param initialNonZeroOddNumber 284 * a non-zero, odd number used as the initial value. This will be the returned 285 * value if no fields are found to include in the hash code 286 * @param multiplierNonZeroOddNumber 287 * a non-zero, odd number used as the multiplier 288 * @param object 289 * the Object to create a <code>hashCode</code> for 290 * @param testTransients 291 * whether to include transient fields 292 * @return int hash code 293 * @throws IllegalArgumentException 294 * if the Object is <code>null</code> 295 * @throws IllegalArgumentException 296 * if the number is zero or even 297 * 298 * @see HashCodeExclude 299 */ 300 public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object, 301 final boolean testTransients) { 302 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null); 303 } 304 305 /** 306 * <p> 307 * Uses reflection to build a valid hash code from the fields of {@code object}. 308 * </p> 309 * 310 * <p> 311 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will 312 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is 313 * also not as efficient as testing explicitly. 314 * </p> 315 * 316 * <p> 317 * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they 318 * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>. 319 * </p> 320 * 321 * <p> 322 * Static fields will not be included. Superclass fields will be included up to and including the specified 323 * superclass. A null superclass is treated as java.lang.Object. 324 * </p> 325 * 326 * <p> 327 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class, 328 * however this is not vital. Prime numbers are preferred, especially for the multiplier. 329 * </p> 330 * 331 * @param <T> 332 * the type of the object involved 333 * @param initialNonZeroOddNumber 334 * a non-zero, odd number used as the initial value. This will be the returned 335 * value if no fields are found to include in the hash code 336 * @param multiplierNonZeroOddNumber 337 * a non-zero, odd number used as the multiplier 338 * @param object 339 * the Object to create a <code>hashCode</code> for 340 * @param testTransients 341 * whether to include transient fields 342 * @param reflectUpToClass 343 * the superclass to reflect up to (inclusive), may be <code>null</code> 344 * @param excludeFields 345 * array of field names to exclude from use in calculation of hash code 346 * @return int hash code 347 * @throws IllegalArgumentException 348 * if the Object is <code>null</code> 349 * @throws IllegalArgumentException 350 * if the number is zero or even 351 * 352 * @see HashCodeExclude 353 * @since 2.0 354 */ 355 public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object, 356 final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) { 357 358 if (object == null) { 359 throw new IllegalArgumentException("The object to build a hash code for must not be null"); 360 } 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</code> 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</code>, 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</code>. 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</code> 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</code> 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</code> 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</code>. 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</code> 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</code> 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</code> 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</code>. 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</code> 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</code> 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<IDKey>(); 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 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 = 0; 540 541 /** 542 * <p> 543 * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>. 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</code> for a <code>boolean</code>. 578 * </p> 579 * <p> 580 * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>. 581 * </p> 582 * <p> 583 * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes 584 * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances 585 * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances 586 * that represent <code>false</code>. 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</code> 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</code> for a <code>boolean</code> array. 604 * </p> 605 * 606 * @param array 607 * the array to add to the <code>hashCode</code> 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</code> for a <code>byte</code>. 626 * </p> 627 * 628 * @param value 629 * the byte to add to the <code>hashCode</code> 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</code> for a <code>byte</code> array. 642 * </p> 643 * 644 * @param array 645 * the array to add to the <code>hashCode</code> 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</code> for a <code>char</code>. 662 * </p> 663 * 664 * @param value 665 * the char to add to the <code>hashCode</code> 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</code> for a <code>char</code> array. 676 * </p> 677 * 678 * @param array 679 * the array to add to the <code>hashCode</code> 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</code> for a <code>double</code>. 696 * </p> 697 * 698 * @param value 699 * the double to add to the <code>hashCode</code> 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</code> for a <code>double</code> array. 709 * </p> 710 * 711 * @param array 712 * the array to add to the <code>hashCode</code> 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</code> for a <code>float</code>. 729 * </p> 730 * 731 * @param value 732 * the float to add to the <code>hashCode</code> 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</code> for a <code>float</code> array. 743 * </p> 744 * 745 * @param array 746 * the array to add to the <code>hashCode</code> 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</code> for an <code>int</code>. 763 * </p> 764 * 765 * @param value 766 * the int to add to the <code>hashCode</code> 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</code> for an <code>int</code> array. 777 * </p> 778 * 779 * @param array 780 * the array to add to the <code>hashCode</code> 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</code> for a <code>long</code>. 797 * </p> 798 * 799 * @param value 800 * the long to add to the <code>hashCode</code> 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</code> for a <code>long</code> array. 815 * </p> 816 * 817 * @param array 818 * the array to add to the <code>hashCode</code> 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</code> for an <code>Object</code>. 835 * </p> 836 * 837 * @param object 838 * the Object to add to the <code>hashCode</code> 839 * @return this 840 */ 841 public HashCodeBuilder append(final Object object) { 842 if (object == null) { 843 iTotal = iTotal * iConstant; 844 845 } else { 846 if (object.getClass().isArray()) { 847 // factor out array case in order to keep method small enough 848 // to be inlined 849 appendArray(object); 850 } else { 851 iTotal = iTotal * iConstant + object.hashCode(); 852 } 853 } 854 return this; 855 } 856 857 /** 858 * <p> 859 * Append a <code>hashCode</code> for an array. 860 * </p> 861 * 862 * @param object 863 * the array to add to the <code>hashCode</code> 864 */ 865 private void appendArray(final Object object) { 866 // 'Switch' on type of array, to dispatch to the correct handler 867 // This handles multi dimensional arrays 868 if (object instanceof long[]) { 869 append((long[]) object); 870 } else if (object instanceof int[]) { 871 append((int[]) object); 872 } else if (object instanceof short[]) { 873 append((short[]) object); 874 } else if (object instanceof char[]) { 875 append((char[]) object); 876 } else if (object instanceof byte[]) { 877 append((byte[]) object); 878 } else if (object instanceof double[]) { 879 append((double[]) object); 880 } else if (object instanceof float[]) { 881 append((float[]) object); 882 } else if (object instanceof boolean[]) { 883 append((boolean[]) object); 884 } else { 885 // Not an array of primitives 886 append((Object[]) object); 887 } 888 } 889 890 /** 891 * <p> 892 * Append a <code>hashCode</code> for an <code>Object</code> array. 893 * </p> 894 * 895 * @param array 896 * the array to add to the <code>hashCode</code> 897 * @return this 898 */ 899 public HashCodeBuilder append(final Object[] array) { 900 if (array == null) { 901 iTotal = iTotal * iConstant; 902 } else { 903 for (final Object element : array) { 904 append(element); 905 } 906 } 907 return this; 908 } 909 910 /** 911 * <p> 912 * Append a <code>hashCode</code> for a <code>short</code>. 913 * </p> 914 * 915 * @param value 916 * the short to add to the <code>hashCode</code> 917 * @return this 918 */ 919 public HashCodeBuilder append(final short value) { 920 iTotal = iTotal * iConstant + value; 921 return this; 922 } 923 924 /** 925 * <p> 926 * Append a <code>hashCode</code> for a <code>short</code> array. 927 * </p> 928 * 929 * @param array 930 * the array to add to the <code>hashCode</code> 931 * @return this 932 */ 933 public HashCodeBuilder append(final short[] array) { 934 if (array == null) { 935 iTotal = iTotal * iConstant; 936 } else { 937 for (final short element : array) { 938 append(element); 939 } 940 } 941 return this; 942 } 943 944 /** 945 * <p> 946 * Adds the result of super.hashCode() to this builder. 947 * </p> 948 * 949 * @param superHashCode 950 * the result of calling <code>super.hashCode()</code> 951 * @return this HashCodeBuilder, used to chain calls. 952 * @since 2.0 953 */ 954 public HashCodeBuilder appendSuper(final int superHashCode) { 955 iTotal = iTotal * iConstant + superHashCode; 956 return this; 957 } 958 959 /** 960 * <p> 961 * Return the computed <code>hashCode</code>. 962 * </p> 963 * 964 * @return <code>hashCode</code> based on the fields appended 965 */ 966 public int toHashCode() { 967 return iTotal; 968 } 969 970 /** 971 * Returns the computed <code>hashCode</code>. 972 * 973 * @return <code>hashCode</code> based on the fields appended 974 * 975 * @since 3.0 976 */ 977 @Override 978 public Integer build() { 979 return Integer.valueOf(toHashCode()); 980 } 981 982 /** 983 * <p> 984 * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood 985 * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for 986 * HashCodeBuilder itself is.</p> 987 * 988 * @return <code>hashCode</code> based on the fields appended 989 * @since 2.5 990 */ 991 @Override 992 public int hashCode() { 993 return toHashCode(); 994 } 995 996}