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