001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.ldap.util; 021 022 023 import java.lang.reflect.AccessibleObject; 024 import java.lang.reflect.Field; 025 import java.lang.reflect.Modifier; 026 027 import org.apache.directory.shared.i18n.I18n; 028 029 030 /** 031 * <p> 032 * Assists in implementing {@link Object#hashCode()} methods. 033 * </p> 034 * <p> 035 * This class enables a good <code>hashCode</code> method to be built for any 036 * class. It follows the rules laid out in the book <a 037 * href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> 038 * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually 039 * quite difficult. This class aims to simplify the process. 040 * </p> 041 * <p> 042 * All relevant fields from the object should be included in the 043 * <code>hashCode</code> method. Derived fields may be excluded. In general, 044 * any field used in the <code>equals</code> method must be used in the 045 * <code>hashCode</code> method. 046 * </p> 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 isSmoker; 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 072 * {@link #appendSuper}. 073 * </p> 074 * <p> 075 * Alternatively, there is a method that uses reflection to determine the fields 076 * to test. Because these fields are usually private, the method, 077 * <code>reflectionHashCode</code>, uses 078 * <code>AccessibleObject.setAccessible</code> to change the visibility of the 079 * fields. This will fail under a security manager, unless the appropriate 080 * permissions are set up correctly. It is also slower than testing explicitly. 081 * </p> 082 * <p> 083 * A typical invocation for this method would look like: 084 * </p> 085 * 086 * <pre> 087 * public int hashCode() 088 * { 089 * return HashCodeBuilder.reflectionHashCode( this ); 090 * } 091 * </pre> 092 * 093 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 094 */ 095 public class HashCodeBuilder 096 { 097 098 /** 099 * Constant to use in building the hashCode. 100 */ 101 private final int iConstant; 102 103 /** 104 * Running total of the hashCode. 105 */ 106 private int iTotal = 0; 107 108 109 /** 110 * <p> 111 * Constructor. 112 * </p> 113 * <p> 114 * This constructor uses two hard coded choices for the constants needed to 115 * build a <code>hashCode</code>. 116 * </p> 117 */ 118 public HashCodeBuilder() 119 { 120 super(); 121 iConstant = 37; 122 iTotal = 17; 123 } 124 125 126 /** 127 * <p> 128 * Constructor. 129 * </p> 130 * <p> 131 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally 132 * these should be different for each class, however this is not vital. 133 * </p> 134 * <p> 135 * Prime numbers are preferred, especially for the multiplier. 136 * </p> 137 * 138 * @param initialNonZeroOddNumber 139 * a non-zero, odd number used as the initial value 140 * @param multiplierNonZeroOddNumber 141 * a non-zero, odd number used as the multiplier 142 * @throws IllegalArgumentException 143 * if the number is zero or even 144 */ 145 public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) 146 { 147 super(); 148 if ( initialNonZeroOddNumber == 0 ) 149 { 150 throw new IllegalArgumentException( I18n.err( I18n.ERR_04384 ) ); 151 } 152 if ( initialNonZeroOddNumber % 2 == 0 ) 153 { 154 throw new IllegalArgumentException( I18n.err( I18n.ERR_04385 ) ); 155 } 156 if ( multiplierNonZeroOddNumber == 0 ) 157 { 158 throw new IllegalArgumentException( I18n.err( I18n.ERR_04386 ) ); 159 } 160 if ( multiplierNonZeroOddNumber % 2 == 0 ) 161 { 162 throw new IllegalArgumentException( I18n.err( I18n.ERR_04387 ) ); 163 } 164 iConstant = multiplierNonZeroOddNumber; 165 iTotal = initialNonZeroOddNumber; 166 } 167 168 169 // ------------------------------------------------------------------------- 170 171 /** 172 * <p> 173 * This method uses reflection to build a valid hash code. 174 * </p> 175 * <p> 176 * This constructor uses two hard coded choices for the constants needed to 177 * build a hash code. 178 * </p> 179 * <p> 180 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 181 * private fields. This means that it will throw a security exception if run 182 * under a security manager, if the permissions are not set up correctly. It 183 * is also not as efficient as testing explicitly. 184 * </p> 185 * <p> 186 * Transient members will be not be used, as they are likely derived fields, 187 * and not part of the value of the <code>Object</code>. 188 * </p> 189 * <p> 190 * Static fields will not be tested. Superclass fields will be included. 191 * </p> 192 * 193 * @param object 194 * the Object to create a <code>hashCode</code> for 195 * @return int hash code 196 * @throws IllegalArgumentException 197 * if the object is <code>null</code> 198 */ 199 public static int reflectionHashCode( Object object ) 200 { 201 return reflectionHashCode( 17, 37, object, false, null ); 202 } 203 204 205 /** 206 * <p> 207 * This method uses reflection to build a valid hash code. 208 * </p> 209 * <p> 210 * This constructor uses two hard coded choices for the constants needed to 211 * build a hash code. 212 * </p> 213 * <p> 214 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 215 * private fields. This means that it will throw a security exception if run 216 * under a security manager, if the permissions are not set up correctly. It 217 * is also not as efficient as testing explicitly. 218 * </p> 219 * <P> 220 * If the TestTransients parameter is set to <code>true</code>, transient 221 * members will be tested, otherwise they are ignored, as they are likely 222 * derived fields, and not part of the value of the <code>Object</code>. 223 * </p> 224 * <p> 225 * Static fields will not be tested. Superclass fields will be included. 226 * </p> 227 * 228 * @param object 229 * the Object to create a <code>hashCode</code> for 230 * @param testTransients 231 * whether to include transient fields 232 * @return int hash code 233 * @throws IllegalArgumentException 234 * if the object is <code>null</code> 235 */ 236 public static int reflectionHashCode( Object object, boolean testTransients ) 237 { 238 return reflectionHashCode( 17, 37, object, testTransients, null ); 239 } 240 241 242 /** 243 * <p> 244 * This method uses reflection to build a valid hash code. 245 * </p> 246 * <p> 247 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 248 * private fields. This means that it will throw a security exception if run 249 * under a security manager, if the permissions are not set up correctly. It 250 * is also not as efficient as testing explicitly. 251 * </p> 252 * <p> 253 * Transient members will be not be used, as they are likely derived fields, 254 * and not part of the value of the <code>Object</code>. 255 * </p> 256 * <p> 257 * Static fields will not be tested. Superclass fields will be included. 258 * </p> 259 * <p> 260 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally 261 * these should be different for each class, however this is not vital. 262 * Prime numbers are preferred, especially for the multiplier. 263 * </p> 264 * 265 * @param initialNonZeroOddNumber 266 * a non-zero, odd number used as the initial value 267 * @param multiplierNonZeroOddNumber 268 * a non-zero, odd number used as the multiplier 269 * @param object 270 * the Object to create a <code>hashCode</code> for 271 * @return int hash code 272 * @throws IllegalArgumentException 273 * if the Object is <code>null</code> 274 * @throws IllegalArgumentException 275 * if the number is zero or even 276 */ 277 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object ) 278 { 279 return reflectionHashCode( initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null ); 280 } 281 282 283 /** 284 * <p> 285 * This method uses reflection to build a valid hash code. 286 * </p> 287 * <p> 288 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 289 * private fields. This means that it will throw a security exception if run 290 * under a security manager, if the permissions are not set up correctly. It 291 * is also not as efficient as testing explicitly. 292 * </p> 293 * <p> 294 * If the TestTransients parameter is set to <code>true</code>, transient 295 * members will be tested, otherwise they are ignored, as they are likely 296 * derived fields, and not part of the value of the <code>Object</code>. 297 * </p> 298 * <p> 299 * Static fields will not be tested. Superclass fields will be included. 300 * </p> 301 * <p> 302 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally 303 * these should be different for each class, however this is not vital. 304 * Prime numbers are preferred, especially for the multiplier. 305 * </p> 306 * 307 * @param initialNonZeroOddNumber 308 * a non-zero, odd number used as the initial value 309 * @param multiplierNonZeroOddNumber 310 * a non-zero, odd number used as the multiplier 311 * @param object 312 * the Object to create a <code>hashCode</code> for 313 * @param testTransients 314 * whether to include transient fields 315 * @return int hash code 316 * @throws IllegalArgumentException 317 * if the Object is <code>null</code> 318 * @throws IllegalArgumentException 319 * if the number is zero or even 320 */ 321 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object, 322 boolean testTransients ) 323 { 324 return reflectionHashCode( initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null ); 325 } 326 327 328 /** 329 * <p> 330 * This method uses reflection to build a valid hash code. 331 * </p> 332 * <p> 333 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 334 * private fields. This means that it will throw a security exception if run 335 * under a security manager, if the permissions are not set up correctly. It 336 * is also not as efficient as testing explicitly. 337 * </p> 338 * <p> 339 * If the TestTransients parameter is set to <code>true</code>, transient 340 * members will be tested, otherwise they are ignored, as they are likely 341 * derived fields, and not part of the value of the <code>Object</code>. 342 * </p> 343 * <p> 344 * Static fields will not be included. Superclass fields will be included up 345 * to and including the specified superclass. A null superclass is treated 346 * as java.lang.Object. 347 * </p> 348 * <p> 349 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally 350 * these should be different for each class, however this is not vital. 351 * Prime numbers are preferred, especially for the multiplier. 352 * </p> 353 * 354 * @param initialNonZeroOddNumber 355 * a non-zero, odd number used as the initial value 356 * @param multiplierNonZeroOddNumber 357 * a non-zero, odd number used as the multiplier 358 * @param object 359 * the Object to create a <code>hashCode</code> for 360 * @param testTransients 361 * whether to include transient fields 362 * @param reflectUpToClass 363 * the superclass to reflect up to (inclusive), may be 364 * <code>null</code> 365 * @return int hash code 366 * @throws IllegalArgumentException 367 * if the Object is <code>null</code> 368 * @throws IllegalArgumentException 369 * if the number is zero or even 370 * @since 2.0 371 */ 372 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object, 373 boolean testTransients, Class reflectUpToClass ) 374 { 375 376 if ( object == null ) 377 { 378 throw new IllegalArgumentException( I18n.err( I18n.ERR_04388 ) ); 379 } 380 HashCodeBuilder builder = new HashCodeBuilder( initialNonZeroOddNumber, multiplierNonZeroOddNumber ); 381 Class clazz = object.getClass(); 382 reflectionAppend( object, clazz, builder, testTransients ); 383 while ( clazz.getSuperclass() != null && clazz != reflectUpToClass ) 384 { 385 clazz = clazz.getSuperclass(); 386 reflectionAppend( object, clazz, builder, testTransients ); 387 } 388 return builder.toHashCode(); 389 } 390 391 392 /** 393 * <p> 394 * Appends the fields and values defined by the given object of the given 395 * <code>Class</code>. 396 * </p> 397 * 398 * @param object 399 * the object to append details of 400 * @param clazz 401 * the class to append details of 402 * @param builder 403 * the builder to append to 404 * @param useTransients 405 * whether to use transient fields 406 */ 407 private static void reflectionAppend( Object object, Class clazz, HashCodeBuilder builder, boolean useTransients ) 408 { 409 Field[] fields = clazz.getDeclaredFields(); 410 AccessibleObject.setAccessible( fields, true ); 411 for ( int i = 0; i < fields.length; i++ ) 412 { 413 Field f = fields[i]; 414 if ( ( f.getName().indexOf( '$' ) == -1 ) && ( useTransients || !Modifier.isTransient( f.getModifiers() ) ) 415 && ( !Modifier.isStatic( f.getModifiers() ) ) ) 416 { 417 try 418 { 419 builder.append( f.get( object ) ); 420 } 421 catch ( IllegalAccessException e ) 422 { 423 // this can't happen. Would get a Security exception instead 424 // throw a runtime exception in case the impossible happens. 425 throw new InternalError( I18n.err( I18n.ERR_04355 ) ); 426 } 427 } 428 } 429 } 430 431 432 // ------------------------------------------------------------------------- 433 434 /** 435 * <p> 436 * Adds the result of super.hashCode() to this builder. 437 * </p> 438 * 439 * @param superHashCode 440 * the result of calling <code>super.hashCode()</code> 441 * @return this HashCodeBuilder, used to chain calls. 442 * @since 2.0 443 */ 444 public HashCodeBuilder appendSuper( int superHashCode ) 445 { 446 iTotal = iTotal * iConstant + superHashCode; 447 return this; 448 } 449 450 451 // ------------------------------------------------------------------------- 452 453 /** 454 * <p> 455 * Append a <code>hashCode</code> for an <code>Object</code>. 456 * </p> 457 * 458 * @param object 459 * the Object to add to the <code>hashCode</code> 460 * @return this 461 */ 462 public HashCodeBuilder append( Object object ) 463 { 464 if ( object == null ) 465 { 466 iTotal = iTotal * iConstant; 467 468 } 469 else 470 { 471 if ( object.getClass().isArray() == false ) 472 { 473 // the simple case, not an array, just the element 474 iTotal = iTotal * iConstant + object.hashCode(); 475 476 } 477 else 478 { 479 // 'Switch' on type of array, to dispatch to the correct handler 480 // This handles multi dimensional arrays 481 if ( object instanceof long[] ) 482 { 483 append( ( long[] ) object ); 484 } 485 else if ( object instanceof int[] ) 486 { 487 append( ( int[] ) object ); 488 } 489 else if ( object instanceof short[] ) 490 { 491 append( ( short[] ) object ); 492 } 493 else if ( object instanceof char[] ) 494 { 495 append( ( char[] ) object ); 496 } 497 else if ( object instanceof byte[] ) 498 { 499 append( ( byte[] ) object ); 500 } 501 else if ( object instanceof double[] ) 502 { 503 append( ( double[] ) object ); 504 } 505 else if ( object instanceof float[] ) 506 { 507 append( ( float[] ) object ); 508 } 509 else if ( object instanceof boolean[] ) 510 { 511 append( ( boolean[] ) object ); 512 } 513 else 514 { 515 // Not an array of primitives 516 append( ( Object[] ) object ); 517 } 518 } 519 } 520 return this; 521 } 522 523 524 /** 525 * <p> 526 * Append a <code>hashCode</code> for a <code>long</code>. 527 * </p> 528 * 529 * @param value 530 * the long to add to the <code>hashCode</code> 531 * @return this 532 */ 533 public HashCodeBuilder append( long value ) 534 { 535 iTotal = iTotal * iConstant + ( ( int ) ( value ^ ( value >> 32 ) ) ); 536 return this; 537 } 538 539 540 /** 541 * <p> 542 * Append a <code>hashCode</code> for an <code>int</code>. 543 * </p> 544 * 545 * @param value 546 * the int to add to the <code>hashCode</code> 547 * @return this 548 */ 549 public HashCodeBuilder append( int value ) 550 { 551 iTotal = iTotal * iConstant + value; 552 return this; 553 } 554 555 556 /** 557 * <p> 558 * Append a <code>hashCode</code> for a <code>short</code>. 559 * </p> 560 * 561 * @param value 562 * the short to add to the <code>hashCode</code> 563 * @return this 564 */ 565 public HashCodeBuilder append( short value ) 566 { 567 iTotal = iTotal * iConstant + value; 568 return this; 569 } 570 571 572 /** 573 * <p> 574 * Append a <code>hashCode</code> for a <code>char</code>. 575 * </p> 576 * 577 * @param value 578 * the char to add to the <code>hashCode</code> 579 * @return this 580 */ 581 public HashCodeBuilder append( char value ) 582 { 583 iTotal = iTotal * iConstant + value; 584 return this; 585 } 586 587 588 /** 589 * <p> 590 * Append a <code>hashCode</code> for a <code>byte</code>. 591 * </p> 592 * 593 * @param value 594 * the byte to add to the <code>hashCode</code> 595 * @return this 596 */ 597 public HashCodeBuilder append( byte value ) 598 { 599 iTotal = iTotal * iConstant + value; 600 return this; 601 } 602 603 604 /** 605 * <p> 606 * Append a <code>hashCode</code> for a <code>double</code>. 607 * </p> 608 * 609 * @param value 610 * the double to add to the <code>hashCode</code> 611 * @return this 612 */ 613 public HashCodeBuilder append( double value ) 614 { 615 return append( Double.doubleToLongBits( value ) ); 616 } 617 618 619 /** 620 * <p> 621 * Append a <code>hashCode</code> for a <code>float</code>. 622 * </p> 623 * 624 * @param value 625 * the float to add to the <code>hashCode</code> 626 * @return this 627 */ 628 public HashCodeBuilder append( float value ) 629 { 630 iTotal = iTotal * iConstant + Float.floatToIntBits( value ); 631 return this; 632 } 633 634 635 /** 636 * <p> 637 * Append a <code>hashCode</code> for a <code>boolean</code>. 638 * </p> 639 * <p> 640 * This adds <code>iConstant * 1</code> to the <code>hashCode</code> and 641 * not a <code>1231</code> or <code>1237</code> as done in 642 * java.lang.Boolean. This is in accordance with the Effective Java design. 643 * </p> 644 * 645 * @param value 646 * the boolean to add to the <code>hashCode</code> 647 * @return this 648 */ 649 public HashCodeBuilder append( boolean value ) 650 { 651 iTotal = iTotal * iConstant + ( value ? 0 : 1 ); 652 return this; 653 } 654 655 656 /** 657 * <p> 658 * Append a <code>hashCode</code> for an <code>Object</code> array. 659 * </p> 660 * 661 * @param array 662 * the array to add to the <code>hashCode</code> 663 * @return this 664 */ 665 public HashCodeBuilder append( Object[] array ) 666 { 667 if ( array == null ) 668 { 669 iTotal = iTotal * iConstant; 670 } 671 else 672 { 673 for ( int i = 0; i < array.length; i++ ) 674 { 675 append( array[i] ); 676 } 677 } 678 return this; 679 } 680 681 682 /** 683 * <p> 684 * Append a <code>hashCode</code> for a <code>long</code> array. 685 * </p> 686 * 687 * @param array 688 * the array to add to the <code>hashCode</code> 689 * @return this 690 */ 691 public HashCodeBuilder append( long[] array ) 692 { 693 if ( array == null ) 694 { 695 iTotal = iTotal * iConstant; 696 } 697 else 698 { 699 for ( int i = 0; i < array.length; i++ ) 700 { 701 append( array[i] ); 702 } 703 } 704 return this; 705 } 706 707 708 /** 709 * <p> 710 * Append a <code>hashCode</code> for an <code>int</code> array. 711 * </p> 712 * 713 * @param array 714 * the array to add to the <code>hashCode</code> 715 * @return this 716 */ 717 public HashCodeBuilder append( int[] array ) 718 { 719 if ( array == null ) 720 { 721 iTotal = iTotal * iConstant; 722 } 723 else 724 { 725 for ( int i = 0; i < array.length; i++ ) 726 { 727 append( array[i] ); 728 } 729 } 730 return this; 731 } 732 733 734 /** 735 * <p> 736 * Append a <code>hashCode</code> for a <code>short</code> array. 737 * </p> 738 * 739 * @param array 740 * the array to add to the <code>hashCode</code> 741 * @return this 742 */ 743 public HashCodeBuilder append( short[] array ) 744 { 745 if ( array == null ) 746 { 747 iTotal = iTotal * iConstant; 748 } 749 else 750 { 751 for ( int i = 0; i < array.length; i++ ) 752 { 753 append( array[i] ); 754 } 755 } 756 return this; 757 } 758 759 760 /** 761 * <p> 762 * Append a <code>hashCode</code> for a <code>char</code> array. 763 * </p> 764 * 765 * @param array 766 * the array to add to the <code>hashCode</code> 767 * @return this 768 */ 769 public HashCodeBuilder append( char[] array ) 770 { 771 if ( array == null ) 772 { 773 iTotal = iTotal * iConstant; 774 } 775 else 776 { 777 for ( int i = 0; i < array.length; i++ ) 778 { 779 append( array[i] ); 780 } 781 } 782 return this; 783 } 784 785 786 /** 787 * <p> 788 * Append a <code>hashCode</code> for a <code>byte</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( byte[] array ) 796 { 797 if ( array == null ) 798 { 799 iTotal = iTotal * iConstant; 800 } 801 else 802 { 803 for ( int i = 0; i < array.length; i++ ) 804 { 805 append( array[i] ); 806 } 807 } 808 return this; 809 } 810 811 812 /** 813 * <p> 814 * Append a <code>hashCode</code> for a <code>double</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( double[] array ) 822 { 823 if ( array == null ) 824 { 825 iTotal = iTotal * iConstant; 826 } 827 else 828 { 829 for ( int i = 0; i < array.length; i++ ) 830 { 831 append( array[i] ); 832 } 833 } 834 return this; 835 } 836 837 838 /** 839 * <p> 840 * Append a <code>hashCode</code> for a <code>float</code> array. 841 * </p> 842 * 843 * @param array 844 * the array to add to the <code>hashCode</code> 845 * @return this 846 */ 847 public HashCodeBuilder append( float[] array ) 848 { 849 if ( array == null ) 850 { 851 iTotal = iTotal * iConstant; 852 } 853 else 854 { 855 for ( int i = 0; i < array.length; i++ ) 856 { 857 append( array[i] ); 858 } 859 } 860 return this; 861 } 862 863 864 /** 865 * <p> 866 * Append a <code>hashCode</code> for a <code>boolean</code> array. 867 * </p> 868 * 869 * @param array 870 * the array to add to the <code>hashCode</code> 871 * @return this 872 */ 873 public HashCodeBuilder append( boolean[] array ) 874 { 875 if ( array == null ) 876 { 877 iTotal = iTotal * iConstant; 878 } 879 else 880 { 881 for ( int i = 0; i < array.length; i++ ) 882 { 883 append( array[i] ); 884 } 885 } 886 return this; 887 } 888 889 890 /** 891 * <p> 892 * Return the computed <code>hashCode</code>. 893 * </p> 894 * 895 * @return <code>hashCode</code> based on the fields appended 896 */ 897 public int toHashCode() 898 { 899 return iTotal; 900 } 901 902 }