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