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 package org.apache.commons.lang.builder; 018 019 import java.lang.reflect.AccessibleObject; 020 import java.lang.reflect.Field; 021 import java.lang.reflect.Modifier; 022 import java.util.Collection; 023 024 import org.apache.commons.lang.ArrayUtils; 025 026 /** 027 * <p>Assists in implementing {@link Object#equals(Object)} methods.</p> 028 * 029 * <p> This class provides methods to build a good equals method for any 030 * class. It follows rules laid out in 031 * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> 032 * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>, 033 * <code>floats</code>, and arrays can be tricky. Also, making sure that 034 * <code>equals()</code> and <code>hashCode()</code> are consistent can be 035 * difficult.</p> 036 * 037 * <p>Two Objects that compare as equals must generate the same hash code, 038 * but two Objects with the same hash code do not have to be equal.</p> 039 * 040 * <p>All relevant fields should be included in the calculation of equals. 041 * Derived fields may be ignored. In particular, any field used in 042 * generating a hash code must be used in the equals method, and vice 043 * versa.</p> 044 * 045 * <p>Typical use for the code is as follows:</p> 046 * <pre> 047 * public boolean equals(Object obj) { 048 * if (obj == null) { return false; } 049 * if (obj == this) { return true; } 050 * if (obj.getClass() != getClass()) { 051 * return false; 052 * } 053 * MyClass rhs = (MyClass) obj; 054 * return new EqualsBuilder() 055 * .appendSuper(super.equals(obj)) 056 * .append(field1, rhs.field1) 057 * .append(field2, rhs.field2) 058 * .append(field3, rhs.field3) 059 * .isEquals(); 060 * } 061 * </pre> 062 * 063 * <p> Alternatively, there is a method that uses reflection to determine 064 * the fields to test. Because these fields are usually private, the method, 065 * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to 066 * change the visibility of the fields. This will fail under a security 067 * manager, unless the appropriate permissions are set up correctly. It is 068 * also slower than testing explicitly.</p> 069 * 070 * <p> A typical invocation for this method would look like:</p> 071 * <pre> 072 * public boolean equals(Object obj) { 073 * return EqualsBuilder.reflectionEquals(this, obj); 074 * } 075 * </pre> 076 * 077 * @author Apache Software Foundation 078 * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a> 079 * @author Gary Gregory 080 * @author Pete Gieser 081 * @author Arun Mammen Thomas 082 * @since 1.0 083 * @version $Id: EqualsBuilder.java 905707 2010-02-02 16:59:59Z niallp $ 084 */ 085 public class EqualsBuilder { 086 087 /** 088 * If the fields tested are equals. 089 * The default value is <code>true</code>. 090 */ 091 private boolean isEquals = true; 092 093 /** 094 * <p>Constructor for EqualsBuilder.</p> 095 * 096 * <p>Starts off assuming that equals is <code>true</code>.</p> 097 * @see Object#equals(Object) 098 */ 099 public EqualsBuilder() { 100 // do nothing for now. 101 } 102 103 //------------------------------------------------------------------------- 104 105 /** 106 * <p>This method uses reflection to determine if the two <code>Object</code>s 107 * are equal.</p> 108 * 109 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 110 * fields. This means that it will throw a security exception if run under 111 * a security manager, if the permissions are not set up correctly. It is also 112 * not as efficient as testing explicitly.</p> 113 * 114 * <p>Transient members will be not be tested, as they are likely derived 115 * fields, and not part of the value of the Object.</p> 116 * 117 * <p>Static fields will not be tested. Superclass fields will be included.</p> 118 * 119 * @param lhs <code>this</code> object 120 * @param rhs the other object 121 * @return <code>true</code> if the two Objects have tested equals. 122 */ 123 public static boolean reflectionEquals(Object lhs, Object rhs) { 124 return reflectionEquals(lhs, rhs, false, null, null); 125 } 126 127 /** 128 * <p>This method uses reflection to determine if the two <code>Object</code>s 129 * are equal.</p> 130 * 131 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 132 * fields. This means that it will throw a security exception if run under 133 * a security manager, if the permissions are not set up correctly. It is also 134 * not as efficient as testing explicitly.</p> 135 * 136 * <p>Transient members will be not be tested, as they are likely derived 137 * fields, and not part of the value of the Object.</p> 138 * 139 * <p>Static fields will not be tested. Superclass fields will be included.</p> 140 * 141 * @param lhs <code>this</code> object 142 * @param rhs the other object 143 * @param excludeFields Collection of String field names to exclude from testing 144 * @return <code>true</code> if the two Objects have tested equals. 145 */ 146 public static boolean reflectionEquals(Object lhs, Object rhs, Collection /*String*/ excludeFields) { 147 return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields)); 148 } 149 150 /** 151 * <p>This method uses reflection to determine if the two <code>Object</code>s 152 * are equal.</p> 153 * 154 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 155 * fields. This means that it will throw a security exception if run under 156 * a security manager, if the permissions are not set up correctly. It is also 157 * not as efficient as testing explicitly.</p> 158 * 159 * <p>Transient members will be not be tested, as they are likely derived 160 * fields, and not part of the value of the Object.</p> 161 * 162 * <p>Static fields will not be tested. Superclass fields will be included.</p> 163 * 164 * @param lhs <code>this</code> object 165 * @param rhs the other object 166 * @param excludeFields array of field names to exclude from testing 167 * @return <code>true</code> if the two Objects have tested equals. 168 */ 169 public static boolean reflectionEquals(Object lhs, Object rhs, String[] excludeFields) { 170 return reflectionEquals(lhs, rhs, false, null, excludeFields); 171 } 172 173 /** 174 * <p>This method uses reflection to determine if the two <code>Object</code>s 175 * are equal.</p> 176 * 177 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 178 * fields. This means that it will throw a security exception if run under 179 * a security manager, if the permissions are not set up correctly. It is also 180 * not as efficient as testing explicitly.</p> 181 * 182 * <p>If the TestTransients parameter is set to <code>true</code>, transient 183 * members will be tested, otherwise they are ignored, as they are likely 184 * derived fields, and not part of the value of the <code>Object</code>.</p> 185 * 186 * <p>Static fields will not be tested. Superclass fields will be included.</p> 187 * 188 * @param lhs <code>this</code> object 189 * @param rhs the other object 190 * @param testTransients whether to include transient fields 191 * @return <code>true</code> if the two Objects have tested equals. 192 */ 193 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) { 194 return reflectionEquals(lhs, rhs, testTransients, null, null); 195 } 196 197 /** 198 * <p>This method uses reflection to determine if the two <code>Object</code>s 199 * are equal.</p> 200 * 201 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 202 * fields. This means that it will throw a security exception if run under 203 * a security manager, if the permissions are not set up correctly. It is also 204 * not as efficient as testing explicitly.</p> 205 * 206 * <p>If the testTransients parameter is set to <code>true</code>, transient 207 * members will be tested, otherwise they are ignored, as they are likely 208 * derived fields, and not part of the value of the <code>Object</code>.</p> 209 * 210 * <p>Static fields will not be included. Superclass fields will be appended 211 * up to and including the specified superclass. A null superclass is treated 212 * as java.lang.Object.</p> 213 * 214 * @param lhs <code>this</code> object 215 * @param rhs the other object 216 * @param testTransients whether to include transient fields 217 * @param reflectUpToClass the superclass to reflect up to (inclusive), 218 * may be <code>null</code> 219 * @return <code>true</code> if the two Objects have tested equals. 220 * @since 2.0 221 */ 222 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) { 223 return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, null); 224 } 225 226 /** 227 * <p>This method uses reflection to determine if the two <code>Object</code>s 228 * are equal.</p> 229 * 230 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 231 * fields. This means that it will throw a security exception if run under 232 * a security manager, if the permissions are not set up correctly. It is also 233 * not as efficient as testing explicitly.</p> 234 * 235 * <p>If the testTransients parameter is set to <code>true</code>, transient 236 * members will be tested, otherwise they are ignored, as they are likely 237 * derived fields, and not part of the value of the <code>Object</code>.</p> 238 * 239 * <p>Static fields will not be included. Superclass fields will be appended 240 * up to and including the specified superclass. A null superclass is treated 241 * as java.lang.Object.</p> 242 * 243 * @param lhs <code>this</code> object 244 * @param rhs the other object 245 * @param testTransients whether to include transient fields 246 * @param reflectUpToClass the superclass to reflect up to (inclusive), 247 * may be <code>null</code> 248 * @param excludeFields array of field names to exclude from testing 249 * @return <code>true</code> if the two Objects have tested equals. 250 * @since 2.0 251 */ 252 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass, 253 String[] excludeFields) { 254 if (lhs == rhs) { 255 return true; 256 } 257 if (lhs == null || rhs == null) { 258 return false; 259 } 260 // Find the leaf class since there may be transients in the leaf 261 // class or in classes between the leaf and root. 262 // If we are not testing transients or a subclass has no ivars, 263 // then a subclass can test equals to a superclass. 264 Class lhsClass = lhs.getClass(); 265 Class rhsClass = rhs.getClass(); 266 Class testClass; 267 if (lhsClass.isInstance(rhs)) { 268 testClass = lhsClass; 269 if (!rhsClass.isInstance(lhs)) { 270 // rhsClass is a subclass of lhsClass 271 testClass = rhsClass; 272 } 273 } else if (rhsClass.isInstance(lhs)) { 274 testClass = rhsClass; 275 if (!lhsClass.isInstance(rhs)) { 276 // lhsClass is a subclass of rhsClass 277 testClass = lhsClass; 278 } 279 } else { 280 // The two classes are not related. 281 return false; 282 } 283 EqualsBuilder equalsBuilder = new EqualsBuilder(); 284 try { 285 reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields); 286 while (testClass.getSuperclass() != null && testClass != reflectUpToClass) { 287 testClass = testClass.getSuperclass(); 288 reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields); 289 } 290 } catch (IllegalArgumentException e) { 291 // In this case, we tried to test a subclass vs. a superclass and 292 // the subclass has ivars or the ivars are transient and 293 // we are testing transients. 294 // If a subclass has ivars that we are trying to test them, we get an 295 // exception and we know that the objects are not equal. 296 return false; 297 } 298 return equalsBuilder.isEquals(); 299 } 300 301 /** 302 * <p>Appends the fields and values defined by the given object of the 303 * given Class.</p> 304 * 305 * @param lhs the left hand object 306 * @param rhs the right hand object 307 * @param clazz the class to append details of 308 * @param builder the builder to append to 309 * @param useTransients whether to test transient fields 310 * @param excludeFields array of field names to exclude from testing 311 */ 312 private static void reflectionAppend( 313 Object lhs, 314 Object rhs, 315 Class clazz, 316 EqualsBuilder builder, 317 boolean useTransients, 318 String[] excludeFields) { 319 Field[] fields = clazz.getDeclaredFields(); 320 AccessibleObject.setAccessible(fields, true); 321 for (int i = 0; i < fields.length && builder.isEquals; i++) { 322 Field f = fields[i]; 323 if (!ArrayUtils.contains(excludeFields, f.getName()) 324 && (f.getName().indexOf('$') == -1) 325 && (useTransients || !Modifier.isTransient(f.getModifiers())) 326 && (!Modifier.isStatic(f.getModifiers()))) { 327 try { 328 builder.append(f.get(lhs), f.get(rhs)); 329 } catch (IllegalAccessException e) { 330 //this can't happen. Would get a Security exception instead 331 //throw a runtime exception in case the impossible happens. 332 throw new InternalError("Unexpected IllegalAccessException"); 333 } 334 } 335 } 336 } 337 338 //------------------------------------------------------------------------- 339 340 /** 341 * <p>Adds the result of <code>super.equals()</code> to this builder.</p> 342 * 343 * @param superEquals the result of calling <code>super.equals()</code> 344 * @return EqualsBuilder - used to chain calls. 345 * @since 2.0 346 */ 347 public EqualsBuilder appendSuper(boolean superEquals) { 348 if (isEquals == false) { 349 return this; 350 } 351 isEquals = superEquals; 352 return this; 353 } 354 355 //------------------------------------------------------------------------- 356 357 /** 358 * <p>Test if two <code>Object</code>s are equal using their 359 * <code>equals</code> method.</p> 360 * 361 * @param lhs the left hand object 362 * @param rhs the right hand object 363 * @return EqualsBuilder - used to chain calls. 364 */ 365 public EqualsBuilder append(Object lhs, Object rhs) { 366 if (isEquals == false) { 367 return this; 368 } 369 if (lhs == rhs) { 370 return this; 371 } 372 if (lhs == null || rhs == null) { 373 this.setEquals(false); 374 return this; 375 } 376 Class lhsClass = lhs.getClass(); 377 if (!lhsClass.isArray()) { 378 // The simple case, not an array, just test the element 379 isEquals = lhs.equals(rhs); 380 } else if (lhs.getClass() != rhs.getClass()) { 381 // Here when we compare different dimensions, for example: a boolean[][] to a boolean[] 382 this.setEquals(false); 383 } 384 // 'Switch' on type of array, to dispatch to the correct handler 385 // This handles multi dimensional arrays of the same depth 386 else if (lhs instanceof long[]) { 387 append((long[]) lhs, (long[]) rhs); 388 } else if (lhs instanceof int[]) { 389 append((int[]) lhs, (int[]) rhs); 390 } else if (lhs instanceof short[]) { 391 append((short[]) lhs, (short[]) rhs); 392 } else if (lhs instanceof char[]) { 393 append((char[]) lhs, (char[]) rhs); 394 } else if (lhs instanceof byte[]) { 395 append((byte[]) lhs, (byte[]) rhs); 396 } else if (lhs instanceof double[]) { 397 append((double[]) lhs, (double[]) rhs); 398 } else if (lhs instanceof float[]) { 399 append((float[]) lhs, (float[]) rhs); 400 } else if (lhs instanceof boolean[]) { 401 append((boolean[]) lhs, (boolean[]) rhs); 402 } else { 403 // Not an array of primitives 404 append((Object[]) lhs, (Object[]) rhs); 405 } 406 return this; 407 } 408 409 /** 410 * <p> 411 * Test if two <code>long</code> s are equal. 412 * </p> 413 * 414 * @param lhs 415 * the left hand <code>long</code> 416 * @param rhs 417 * the right hand <code>long</code> 418 * @return EqualsBuilder - used to chain calls. 419 */ 420 public EqualsBuilder append(long lhs, long rhs) { 421 if (isEquals == false) { 422 return this; 423 } 424 isEquals = (lhs == rhs); 425 return this; 426 } 427 428 /** 429 * <p>Test if two <code>int</code>s are equal.</p> 430 * 431 * @param lhs the left hand <code>int</code> 432 * @param rhs the right hand <code>int</code> 433 * @return EqualsBuilder - used to chain calls. 434 */ 435 public EqualsBuilder append(int lhs, int rhs) { 436 if (isEquals == false) { 437 return this; 438 } 439 isEquals = (lhs == rhs); 440 return this; 441 } 442 443 /** 444 * <p>Test if two <code>short</code>s are equal.</p> 445 * 446 * @param lhs the left hand <code>short</code> 447 * @param rhs the right hand <code>short</code> 448 * @return EqualsBuilder - used to chain calls. 449 */ 450 public EqualsBuilder append(short lhs, short rhs) { 451 if (isEquals == false) { 452 return this; 453 } 454 isEquals = (lhs == rhs); 455 return this; 456 } 457 458 /** 459 * <p>Test if two <code>char</code>s are equal.</p> 460 * 461 * @param lhs the left hand <code>char</code> 462 * @param rhs the right hand <code>char</code> 463 * @return EqualsBuilder - used to chain calls. 464 */ 465 public EqualsBuilder append(char lhs, char rhs) { 466 if (isEquals == false) { 467 return this; 468 } 469 isEquals = (lhs == rhs); 470 return this; 471 } 472 473 /** 474 * <p>Test if two <code>byte</code>s are equal.</p> 475 * 476 * @param lhs the left hand <code>byte</code> 477 * @param rhs the right hand <code>byte</code> 478 * @return EqualsBuilder - used to chain calls. 479 */ 480 public EqualsBuilder append(byte lhs, byte rhs) { 481 if (isEquals == false) { 482 return this; 483 } 484 isEquals = (lhs == rhs); 485 return this; 486 } 487 488 /** 489 * <p>Test if two <code>double</code>s are equal by testing that the 490 * pattern of bits returned by <code>doubleToLong</code> are equal.</p> 491 * 492 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 493 * 494 * <p>It is compatible with the hash code generated by 495 * <code>HashCodeBuilder</code>.</p> 496 * 497 * @param lhs the left hand <code>double</code> 498 * @param rhs the right hand <code>double</code> 499 * @return EqualsBuilder - used to chain calls. 500 */ 501 public EqualsBuilder append(double lhs, double rhs) { 502 if (isEquals == false) { 503 return this; 504 } 505 return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs)); 506 } 507 508 /** 509 * <p>Test if two <code>float</code>s are equal byt testing that the 510 * pattern of bits returned by doubleToLong are equal.</p> 511 * 512 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 513 * 514 * <p>It is compatible with the hash code generated by 515 * <code>HashCodeBuilder</code>.</p> 516 * 517 * @param lhs the left hand <code>float</code> 518 * @param rhs the right hand <code>float</code> 519 * @return EqualsBuilder - used to chain calls. 520 */ 521 public EqualsBuilder append(float lhs, float rhs) { 522 if (isEquals == false) { 523 return this; 524 } 525 return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs)); 526 } 527 528 /** 529 * <p>Test if two <code>booleans</code>s are equal.</p> 530 * 531 * @param lhs the left hand <code>boolean</code> 532 * @param rhs the right hand <code>boolean</code> 533 * @return EqualsBuilder - used to chain calls. 534 */ 535 public EqualsBuilder append(boolean lhs, boolean rhs) { 536 if (isEquals == false) { 537 return this; 538 } 539 isEquals = (lhs == rhs); 540 return this; 541 } 542 543 /** 544 * <p>Performs a deep comparison of two <code>Object</code> arrays.</p> 545 * 546 * <p>This also will be called for the top level of 547 * multi-dimensional, ragged, and multi-typed arrays.</p> 548 * 549 * @param lhs the left hand <code>Object[]</code> 550 * @param rhs the right hand <code>Object[]</code> 551 * @return EqualsBuilder - used to chain calls. 552 */ 553 public EqualsBuilder append(Object[] lhs, Object[] rhs) { 554 if (isEquals == false) { 555 return this; 556 } 557 if (lhs == rhs) { 558 return this; 559 } 560 if (lhs == null || rhs == null) { 561 this.setEquals(false); 562 return this; 563 } 564 if (lhs.length != rhs.length) { 565 this.setEquals(false); 566 return this; 567 } 568 for (int i = 0; i < lhs.length && isEquals; ++i) { 569 append(lhs[i], rhs[i]); 570 } 571 return this; 572 } 573 574 /** 575 * <p>Deep comparison of array of <code>long</code>. Length and all 576 * values are compared.</p> 577 * 578 * <p>The method {@link #append(long, long)} is used.</p> 579 * 580 * @param lhs the left hand <code>long[]</code> 581 * @param rhs the right hand <code>long[]</code> 582 * @return EqualsBuilder - used to chain calls. 583 */ 584 public EqualsBuilder append(long[] lhs, long[] rhs) { 585 if (isEquals == false) { 586 return this; 587 } 588 if (lhs == rhs) { 589 return this; 590 } 591 if (lhs == null || rhs == null) { 592 this.setEquals(false); 593 return this; 594 } 595 if (lhs.length != rhs.length) { 596 this.setEquals(false); 597 return this; 598 } 599 for (int i = 0; i < lhs.length && isEquals; ++i) { 600 append(lhs[i], rhs[i]); 601 } 602 return this; 603 } 604 605 /** 606 * <p>Deep comparison of array of <code>int</code>. Length and all 607 * values are compared.</p> 608 * 609 * <p>The method {@link #append(int, int)} is used.</p> 610 * 611 * @param lhs the left hand <code>int[]</code> 612 * @param rhs the right hand <code>int[]</code> 613 * @return EqualsBuilder - used to chain calls. 614 */ 615 public EqualsBuilder append(int[] lhs, int[] rhs) { 616 if (isEquals == false) { 617 return this; 618 } 619 if (lhs == rhs) { 620 return this; 621 } 622 if (lhs == null || rhs == null) { 623 this.setEquals(false); 624 return this; 625 } 626 if (lhs.length != rhs.length) { 627 this.setEquals(false); 628 return this; 629 } 630 for (int i = 0; i < lhs.length && isEquals; ++i) { 631 append(lhs[i], rhs[i]); 632 } 633 return this; 634 } 635 636 /** 637 * <p>Deep comparison of array of <code>short</code>. Length and all 638 * values are compared.</p> 639 * 640 * <p>The method {@link #append(short, short)} is used.</p> 641 * 642 * @param lhs the left hand <code>short[]</code> 643 * @param rhs the right hand <code>short[]</code> 644 * @return EqualsBuilder - used to chain calls. 645 */ 646 public EqualsBuilder append(short[] lhs, short[] rhs) { 647 if (isEquals == false) { 648 return this; 649 } 650 if (lhs == rhs) { 651 return this; 652 } 653 if (lhs == null || rhs == null) { 654 this.setEquals(false); 655 return this; 656 } 657 if (lhs.length != rhs.length) { 658 this.setEquals(false); 659 return this; 660 } 661 for (int i = 0; i < lhs.length && isEquals; ++i) { 662 append(lhs[i], rhs[i]); 663 } 664 return this; 665 } 666 667 /** 668 * <p>Deep comparison of array of <code>char</code>. Length and all 669 * values are compared.</p> 670 * 671 * <p>The method {@link #append(char, char)} is used.</p> 672 * 673 * @param lhs the left hand <code>char[]</code> 674 * @param rhs the right hand <code>char[]</code> 675 * @return EqualsBuilder - used to chain calls. 676 */ 677 public EqualsBuilder append(char[] lhs, char[] rhs) { 678 if (isEquals == false) { 679 return this; 680 } 681 if (lhs == rhs) { 682 return this; 683 } 684 if (lhs == null || rhs == null) { 685 this.setEquals(false); 686 return this; 687 } 688 if (lhs.length != rhs.length) { 689 this.setEquals(false); 690 return this; 691 } 692 for (int i = 0; i < lhs.length && isEquals; ++i) { 693 append(lhs[i], rhs[i]); 694 } 695 return this; 696 } 697 698 /** 699 * <p>Deep comparison of array of <code>byte</code>. Length and all 700 * values are compared.</p> 701 * 702 * <p>The method {@link #append(byte, byte)} is used.</p> 703 * 704 * @param lhs the left hand <code>byte[]</code> 705 * @param rhs the right hand <code>byte[]</code> 706 * @return EqualsBuilder - used to chain calls. 707 */ 708 public EqualsBuilder append(byte[] lhs, byte[] rhs) { 709 if (isEquals == false) { 710 return this; 711 } 712 if (lhs == rhs) { 713 return this; 714 } 715 if (lhs == null || rhs == null) { 716 this.setEquals(false); 717 return this; 718 } 719 if (lhs.length != rhs.length) { 720 this.setEquals(false); 721 return this; 722 } 723 for (int i = 0; i < lhs.length && isEquals; ++i) { 724 append(lhs[i], rhs[i]); 725 } 726 return this; 727 } 728 729 /** 730 * <p>Deep comparison of array of <code>double</code>. Length and all 731 * values are compared.</p> 732 * 733 * <p>The method {@link #append(double, double)} is used.</p> 734 * 735 * @param lhs the left hand <code>double[]</code> 736 * @param rhs the right hand <code>double[]</code> 737 * @return EqualsBuilder - used to chain calls. 738 */ 739 public EqualsBuilder append(double[] lhs, double[] rhs) { 740 if (isEquals == false) { 741 return this; 742 } 743 if (lhs == rhs) { 744 return this; 745 } 746 if (lhs == null || rhs == null) { 747 this.setEquals(false); 748 return this; 749 } 750 if (lhs.length != rhs.length) { 751 this.setEquals(false); 752 return this; 753 } 754 for (int i = 0; i < lhs.length && isEquals; ++i) { 755 append(lhs[i], rhs[i]); 756 } 757 return this; 758 } 759 760 /** 761 * <p>Deep comparison of array of <code>float</code>. Length and all 762 * values are compared.</p> 763 * 764 * <p>The method {@link #append(float, float)} is used.</p> 765 * 766 * @param lhs the left hand <code>float[]</code> 767 * @param rhs the right hand <code>float[]</code> 768 * @return EqualsBuilder - used to chain calls. 769 */ 770 public EqualsBuilder append(float[] lhs, float[] rhs) { 771 if (isEquals == false) { 772 return this; 773 } 774 if (lhs == rhs) { 775 return this; 776 } 777 if (lhs == null || rhs == null) { 778 this.setEquals(false); 779 return this; 780 } 781 if (lhs.length != rhs.length) { 782 this.setEquals(false); 783 return this; 784 } 785 for (int i = 0; i < lhs.length && isEquals; ++i) { 786 append(lhs[i], rhs[i]); 787 } 788 return this; 789 } 790 791 /** 792 * <p>Deep comparison of array of <code>boolean</code>. Length and all 793 * values are compared.</p> 794 * 795 * <p>The method {@link #append(boolean, boolean)} is used.</p> 796 * 797 * @param lhs the left hand <code>boolean[]</code> 798 * @param rhs the right hand <code>boolean[]</code> 799 * @return EqualsBuilder - used to chain calls. 800 */ 801 public EqualsBuilder append(boolean[] lhs, boolean[] rhs) { 802 if (isEquals == false) { 803 return this; 804 } 805 if (lhs == rhs) { 806 return this; 807 } 808 if (lhs == null || rhs == null) { 809 this.setEquals(false); 810 return this; 811 } 812 if (lhs.length != rhs.length) { 813 this.setEquals(false); 814 return this; 815 } 816 for (int i = 0; i < lhs.length && isEquals; ++i) { 817 append(lhs[i], rhs[i]); 818 } 819 return this; 820 } 821 822 /** 823 * <p>Returns <code>true</code> if the fields that have been checked 824 * are all equal.</p> 825 * 826 * @return boolean 827 */ 828 public boolean isEquals() { 829 return this.isEquals; 830 } 831 832 /** 833 * Sets the <code>isEquals</code> value. 834 * 835 * @param isEquals The value to set. 836 * @since 2.1 837 */ 838 protected void setEquals(boolean isEquals) { 839 this.isEquals = isEquals; 840 } 841 842 /** 843 * Reset the EqualsBuilder so you can use the same object again 844 * @since 2.5 845 */ 846 public void reset() { 847 this.isEquals = true; 848 } 849 }