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