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