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