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 * https://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 */ 017package org.apache.commons.lang3.builder; 018 019import java.lang.reflect.Field; 020import java.lang.reflect.Modifier; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Set; 026 027import org.apache.commons.lang3.ArrayUtils; 028import org.apache.commons.lang3.ClassUtils; 029import org.apache.commons.lang3.tuple.Pair; 030 031/** 032 * Assists in implementing {@link Object#equals(Object)} methods. 033 * 034 * <p> 035 * This class provides methods to build a good equals method for any 036 * class. It follows rules laid out in 037 * <a href="https://www.oracle.com/java/technologies/effectivejava.html">Effective Java</a> 038 * , by Joshua Bloch. In particular the rule for comparing {@code doubles}, 039 * {@code floats}, and arrays can be tricky. Also, making sure that 040 * {@code equals()} and {@code hashCode()} are consistent can be 041 * difficult. 042 * </p> 043 * 044 * <p> 045 * Two Objects that compare as equals must generate the same hash code, 046 * but two Objects with the same hash code do not have to be equal. 047 * </p> 048 * 049 * <p> 050 * All relevant fields should be included in the calculation of equals. 051 * Derived fields may be ignored. In particular, any field used in 052 * generating a hash code must be used in the equals method, and vice 053 * versa. 054 * </p> 055 * 056 * <p> 057 * Typical use for the code is as follows: 058 * </p> 059 * <pre> 060 * public boolean equals(Object obj) { 061 * if (obj == null) { return false; } 062 * if (obj == this) { return true; } 063 * if (obj.getClass() != getClass()) { 064 * return false; 065 * } 066 * MyClass rhs = (MyClass) obj; 067 * return new EqualsBuilder() 068 * .appendSuper(super.equals(obj)) 069 * .append(field1, rhs.field1) 070 * .append(field2, rhs.field2) 071 * .append(field3, rhs.field3) 072 * .isEquals(); 073 * } 074 * </pre> 075 * 076 * <p> 077 * Alternatively, there is a method that uses reflection to determine 078 * the fields to test. Because these fields are usually private, the method, 079 * {@code reflectionEquals}, uses {@code AccessibleObject.setAccessible} to 080 * change the visibility of the fields. This will fail under a security 081 * manager, unless the appropriate permissions are set up correctly. It is 082 * also slower than testing explicitly. Non-primitive fields are compared using 083 * {@code equals()}. 084 * </p> 085 * <p> 086 * See also {@link AbstractBuilder#setForceAccessible(boolean)} 087 * </p> 088 * 089 * <p> 090 * A typical invocation for this method would look like: 091 * </p> 092 * <pre> 093 * public boolean equals(Object obj) { 094 * return EqualsBuilder.reflectionEquals(this, obj); 095 * } 096 * </pre> 097 * 098 * <p> 099 * The {@link EqualsExclude} annotation can be used to exclude fields from being 100 * used by the {@code reflectionEquals} methods. 101 * </p> 102 * 103 * @since 1.0 104 * @see AbstractBuilder#setForceAccessible(boolean) 105 */ 106public class EqualsBuilder extends AbstractReflection implements Builder<Boolean> { 107 108 /** 109 * Builds instances of CompareToBuilder. 110 */ 111 public static class Builder extends AbstractBuilder<Builder> { 112 113 /** 114 * Constructs a new Builder instance. 115 */ 116 private Builder() { 117 // empty 118 } 119 120 @Override 121 public EqualsBuilder get() { 122 return new EqualsBuilder(this); 123 } 124 125 } 126 127 /** 128 * A registry of objects to detect cyclical object references, avoid infinite loops, and stack overflows. 129 */ 130 private static final ThreadLocal<Set<Pair<IDKey, IDKey>>> REGISTRY = ThreadLocal.withInitial(HashSet::new); 131 132 /** 133 * Constructs a new Builder. 134 * 135 * @return A new Builder. 136 */ 137 public static Builder builder() { 138 return new Builder(); 139 } 140 141 /* 142 * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode() 143 * we are in the process of calculating. 144 * 145 * So we generate a one-to-one mapping from the original object to a new object. 146 * 147 * Now HashSet uses equals() to determine if two elements with the same hash code really 148 * are equal, so we also need to ensure that the replacement objects are only equal 149 * if the original objects are identical. 150 * 151 * The original implementation (2.4 and before) used the System.identityHashCode() 152 * method - however this is not guaranteed to generate unique ids (e.g. LANG-459) 153 * 154 * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey) 155 * to disambiguate the duplicate ids. 156 */ 157 158 /** 159 * Gets the registry of object pairs being traversed by the reflection 160 * methods in the current thread. 161 * 162 * @return Set the registry of objects being traversed 163 */ 164 static Set<Pair<IDKey, IDKey>> getRegistry() { 165 return REGISTRY.get(); 166 } 167 168 /** 169 * Tests whether the registry contains the given object pair. 170 * <p> 171 * Used by the reflection methods to avoid infinite loops. 172 * Objects might be swapped therefore a check is needed if the object pair 173 * is registered in the given or swapped order. 174 * </p> 175 * 176 * @param lhs {@code this} object to lookup in registry 177 * @param rhs The other object to lookup on registry 178 * @return boolean {@code true} if the registry contains the given object. 179 */ 180 static boolean isRegistered(final Object lhs, final Object rhs) { 181 return isRegistered(lhs, rhs, getRegistry()); 182 } 183 184 /** 185 * Uses reflection to determine if the two {@link Object}s 186 * are equal. 187 * 188 * <p> 189 * It uses {@code AccessibleObject.setAccessible} to gain access to private 190 * fields. This means that it will throw a security exception if run under 191 * a security manager, if the permissions are not set up correctly. It is also 192 * not as efficient as testing explicitly. Non-primitive fields are compared using 193 * {@code equals()}. 194 * </p> 195 * 196 * <p> 197 * If the TestTransients parameter is set to {@code true}, transient 198 * members will be tested, otherwise they are ignored, as they are likely 199 * derived fields, and not part of the value of the {@link Object}. 200 * </p> 201 * 202 * <p> 203 * Static fields will not be tested. Superclass fields will be included. 204 * </p> 205 * 206 * @param lhs {@code this} object 207 * @param rhs The other object 208 * @param testTransients whether to include transient fields 209 * @return {@code true} if the two Objects have tested equals. 210 * @see EqualsExclude 211 */ 212 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients) { 213 return reflectionEquals(lhs, rhs, testTransients, null); 214 } 215 216 /** 217 * Uses reflection to determine if the two {@link Object}s 218 * are equal. 219 * 220 * <p> 221 * It uses {@code AccessibleObject.setAccessible} to gain access to private 222 * fields. This means that it will throw a security exception if run under 223 * a security manager, if the permissions are not set up correctly. It is also 224 * not as efficient as testing explicitly. Non-primitive fields are compared using 225 * {@code equals()}. 226 * </p> 227 * 228 * <p> 229 * If the testTransients parameter is set to {@code true}, transient 230 * members will be tested, otherwise they are ignored, as they are likely 231 * derived fields, and not part of the value of the {@link Object}. 232 * </p> 233 * 234 * <p> 235 * Static fields will not be included. Superclass fields will be appended 236 * up to and including the specified superclass. A null superclass is treated 237 * as java.lang.Object. 238 * </p> 239 * 240 * <p> 241 * If the testRecursive parameter is set to {@code true}, non primitive 242 * (and non primitive wrapper) field types will be compared by 243 * {@link EqualsBuilder} recursively instead of invoking their 244 * {@code equals()} method. Leading to a deep reflection equals test. 245 * 246 * <p> 247 * Note on graph shape: the internal registry that prevents infinite recursion on 248 * cyclic object graphs is a visit stack, not a visited set - object pairs reachable 249 * more than once through shared (acyclic) references are re-compared on every path. 250 * On deeply nested graphs with many shared references (reference "diamonds"), the 251 * comparison cost can grow exponentially with nesting depth. Do not use recursive 252 * reflection equality on object graphs built from untrusted input (for example, 253 * graphs materialized by an identity-preserving deserializer). 254 * </p> 255 * 256 * @param lhs {@code this} object 257 * @param rhs The other object 258 * @param testTransients whether to include transient fields 259 * @param reflectUpToClass The superclass to reflect up to (inclusive), 260 * may be {@code null} 261 * @param testRecursive whether to call reflection equals on non-primitive 262 * fields recursively. 263 * @param excludeFields array of field names to exclude from testing 264 * @return {@code true} if the two Objects have tested equals. 265 * @see EqualsExclude 266 * @since 3.6 267 */ 268 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass, 269 final boolean testRecursive, final String... excludeFields) { 270 if (lhs == rhs) { 271 return true; 272 } 273 if (lhs == null || rhs == null) { 274 return false; 275 } 276 // @formatter:off 277 return new EqualsBuilder() 278 .setExcludeFields(excludeFields) 279 .setReflectUpToClass(reflectUpToClass) 280 .setTestTransients(testTransients) 281 .setTestRecursive(testRecursive) 282 .reflectionAppend(lhs, rhs) 283 .isEquals(); 284 // @formatter:on 285 } 286 287 /** 288 * Uses reflection to determine if the two {@link Object}s 289 * are equal. 290 * 291 * <p> 292 * It uses {@code AccessibleObject.setAccessible} to gain access to private 293 * fields. This means that it will throw a security exception if run under 294 * a security manager, if the permissions are not set up correctly. It is also 295 * not as efficient as testing explicitly. Non-primitive fields are compared using 296 * {@code equals()}. 297 * </p> 298 * 299 * <p> 300 * If the testTransients parameter is set to {@code true}, transient 301 * members will be tested, otherwise they are ignored, as they are likely 302 * derived fields, and not part of the value of the {@link Object}. 303 * </p> 304 * 305 * <p> 306 * Static fields will not be included. Superclass fields will be appended 307 * up to and including the specified superclass. A null superclass is treated 308 * as java.lang.Object. 309 * </p> 310 * 311 * @param lhs {@code this} object 312 * @param rhs The other object 313 * @param testTransients whether to include transient fields 314 * @param reflectUpToClass The superclass to reflect up to (inclusive), 315 * may be {@code null} 316 * @param excludeFields array of field names to exclude from testing 317 * @return {@code true} if the two Objects have tested equals. 318 * @see EqualsExclude 319 * @since 2.0 320 */ 321 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass, 322 final String... excludeFields) { 323 return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, false, excludeFields); 324 } 325 326 /** 327 * Uses reflection to determine if the two {@link Object}s 328 * are equal. 329 * 330 * <p> 331 * It uses {@code AccessibleObject.setAccessible} to gain access to private 332 * fields. This means that it will throw a security exception if run under 333 * a security manager, if the permissions are not set up correctly. It is also 334 * not as efficient as testing explicitly. Non-primitive fields are compared using 335 * {@code equals()}. 336 * </p> 337 * 338 * <p> 339 * Transient members will be not be tested, as they are likely derived 340 * fields, and not part of the value of the Object. 341 * </p> 342 * 343 * <p> 344 * Static fields will not be tested. Superclass fields will be included. 345 * </p> 346 * 347 * @param lhs {@code this} object 348 * @param rhs The other object 349 * @param excludeFields Collection of String field names to exclude from testing 350 * @return {@code true} if the two Objects have tested equals. 351 * @see EqualsExclude 352 */ 353 public static boolean reflectionEquals(final Object lhs, final Object rhs, final Collection<String> excludeFields) { 354 return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields)); 355 } 356 357 /** 358 * Uses reflection to determine if the two {@link Object}s 359 * are equal. 360 * 361 * <p> 362 * It uses {@code AccessibleObject.setAccessible} to gain access to private 363 * fields. This means that it will throw a security exception if run under 364 * a security manager, if the permissions are not set up correctly. It is also 365 * not as efficient as testing explicitly. Non-primitive fields are compared using 366 * {@code equals()}. 367 * </p> 368 * 369 * <p> 370 * Transient members will be not be tested, as they are likely derived 371 * fields, and not part of the value of the Object. 372 * </p> 373 * 374 * <p> 375 * Static fields will not be tested. Superclass fields will be included. 376 * </p> 377 * 378 * @param lhs {@code this} object 379 * @param rhs The other object 380 * @param excludeFields array of field names to exclude from testing 381 * @return {@code true} if the two Objects have tested equals. 382 * @see EqualsExclude 383 */ 384 public static boolean reflectionEquals(final Object lhs, final Object rhs, final String... excludeFields) { 385 return reflectionEquals(lhs, rhs, false, null, excludeFields); 386 } 387 388 /** 389 * Registers the given object pair. 390 * Used by the reflection methods to avoid infinite loops. 391 * 392 * @param lhs {@code this} object to register 393 * @param rhs The other object to register 394 */ 395 private static void register(final Object lhs, final Object rhs) { 396 register(lhs, rhs, getRegistry()); 397 } 398 399 /** 400 * Unregisters the given object pair. 401 * 402 * <p> 403 * Used by the reflection methods to avoid infinite loops. 404 * </p> 405 * 406 * @param lhs {@code this} object to unregister 407 * @param rhs The other object to unregister 408 */ 409 private static void unregister(final Object lhs, final Object rhs) { 410 unregister(lhs, rhs, getRegistry(), REGISTRY); 411 } 412 413 /** 414 * If the fields tested are equals. 415 * The default value is {@code true}. 416 */ 417 private boolean isEquals = true; 418 419 private boolean testTransients; 420 421 private boolean testRecursive; 422 423 private List<Class<?>> bypassReflectionClasses; 424 425 private Class<?> reflectUpToClass; 426 427 private String[] excludeFields; 428 429 /** 430 * Constructor for EqualsBuilder. 431 * 432 * <p> 433 * Starts off assuming that equals is {@code true}. 434 * </p> 435 * 436 * @see Object#equals(Object) 437 */ 438 public EqualsBuilder() { 439 super(builder()); 440 // set up default classes to bypass reflection for 441 bypassReflectionClasses = new ArrayList<>(1); 442 bypassReflectionClasses.add(String.class); //hashCode field being lazy but not transient 443 } 444 445 private EqualsBuilder(final Builder builder) { 446 super(builder); 447 } 448 449 /** 450 * Test if two {@code booleans}s are equal. 451 * 452 * @param lhs The left-hand side {@code boolean} 453 * @param rhs The right-hand side {@code boolean} 454 * @return {@code this} instance. 455 */ 456 public EqualsBuilder append(final boolean lhs, final boolean rhs) { 457 if (!isEquals) { 458 return this; 459 } 460 isEquals = lhs == rhs; 461 return this; 462 } 463 464 /** 465 * Deep comparison of array of {@code boolean}. Length and all 466 * values are compared. 467 * 468 * <p> 469 * The method {@link #append(boolean, boolean)} is used. 470 * </p> 471 * 472 * @param lhs The left-hand side {@code boolean[]} 473 * @param rhs The right-hand side {@code boolean[]} 474 * @return {@code this} instance. 475 */ 476 public EqualsBuilder append(final boolean[] lhs, final boolean[] rhs) { 477 if (!isEquals || lhs == rhs) { 478 return this; 479 } 480 if (lhs == null || rhs == null || lhs.length != rhs.length) { 481 setEquals(false); 482 return this; 483 } 484 for (int i = 0; i < lhs.length && isEquals; ++i) { 485 append(lhs[i], rhs[i]); 486 } 487 return this; 488 } 489 490 /** 491 * Test if two {@code byte}s are equal. 492 * 493 * @param lhs The left-hand side {@code byte} 494 * @param rhs The right-hand side {@code byte} 495 * @return {@code this} instance. 496 */ 497 public EqualsBuilder append(final byte lhs, final byte rhs) { 498 if (isEquals) { 499 isEquals = lhs == rhs; 500 } 501 return this; 502 } 503 504 /** 505 * Deep comparison of array of {@code byte}. Length and all 506 * values are compared. 507 * 508 * <p> 509 * The method {@link #append(byte, byte)} is used. 510 * </p> 511 * 512 * @param lhs The left-hand side {@code byte[]} 513 * @param rhs The right-hand side {@code byte[]} 514 * @return {@code this} instance. 515 */ 516 public EqualsBuilder append(final byte[] lhs, final byte[] rhs) { 517 if (!isEquals || lhs == rhs) { 518 return this; 519 } 520 if (lhs == null || rhs == null || lhs.length != rhs.length) { 521 setEquals(false); 522 return this; 523 } 524 for (int i = 0; i < lhs.length && isEquals; ++i) { 525 append(lhs[i], rhs[i]); 526 } 527 return this; 528 } 529 530 /** 531 * Test if two {@code char}s are equal. 532 * 533 * @param lhs The left-hand side {@code char} 534 * @param rhs The right-hand side {@code char} 535 * @return {@code this} instance. 536 */ 537 public EqualsBuilder append(final char lhs, final char rhs) { 538 if (isEquals) { 539 isEquals = lhs == rhs; 540 } 541 return this; 542 } 543 544 /** 545 * Deep comparison of array of {@code char}. Length and all 546 * values are compared. 547 * 548 * <p> 549 * The method {@link #append(char, char)} is used. 550 * </p> 551 * 552 * @param lhs The left-hand side {@code char[]} 553 * @param rhs The right-hand side {@code char[]} 554 * @return {@code this} instance. 555 */ 556 public EqualsBuilder append(final char[] lhs, final char[] rhs) { 557 if (!isEquals || lhs == rhs) { 558 return this; 559 } 560 if (lhs == null || rhs == null || lhs.length != rhs.length) { 561 setEquals(false); 562 return this; 563 } 564 for (int i = 0; i < lhs.length && isEquals; ++i) { 565 append(lhs[i], rhs[i]); 566 } 567 return this; 568 } 569 570 /** 571 * Test if two {@code double}s are equal by testing that the 572 * pattern of bits returned by {@code doubleToLong} are equal. 573 * 574 * <p> 575 * This handles NaNs, Infinities, and {@code -0.0}. 576 * </p> 577 * 578 * <p> 579 * It is compatible with the hash code generated by 580 * {@link HashCodeBuilder}. 581 * </p> 582 * 583 * @param lhs The left-hand side {@code double} 584 * @param rhs The right-hand side {@code double} 585 * @return {@code this} instance. 586 */ 587 public EqualsBuilder append(final double lhs, final double rhs) { 588 if (isEquals) { 589 return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs)); 590 } 591 return this; 592 } 593 594 /** 595 * Deep comparison of array of {@code double}. Length and all 596 * values are compared. 597 * 598 * <p> 599 * The method {@link #append(double, double)} is used. 600 * </p> 601 * 602 * @param lhs The left-hand side {@code double[]} 603 * @param rhs The right-hand side {@code double[]} 604 * @return {@code this} instance. 605 */ 606 public EqualsBuilder append(final double[] lhs, final double[] rhs) { 607 if (!isEquals || lhs == rhs) { 608 return this; 609 } 610 if (lhs == null || rhs == null || lhs.length != rhs.length) { 611 setEquals(false); 612 return this; 613 } 614 for (int i = 0; i < lhs.length && isEquals; ++i) { 615 append(lhs[i], rhs[i]); 616 } 617 return this; 618 } 619 620 /** 621 * Test if two {@code float}s are equal by testing that the 622 * pattern of bits returned by doubleToLong are equal. 623 * 624 * <p> 625 * This handles NaNs, Infinities, and {@code -0.0}. 626 * </p> 627 * 628 * <p> 629 * It is compatible with the hash code generated by 630 * {@link HashCodeBuilder}. 631 * </p> 632 * 633 * @param lhs The left-hand side {@code float} 634 * @param rhs The right-hand side {@code float} 635 * @return {@code this} instance. 636 */ 637 public EqualsBuilder append(final float lhs, final float rhs) { 638 if (isEquals) { 639 return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs)); 640 } 641 return this; 642 } 643 644 /** 645 * Deep comparison of array of {@code float}. Length and all 646 * values are compared. 647 * 648 * <p> 649 * The method {@link #append(float, float)} is used. 650 * </p> 651 * 652 * @param lhs The left-hand side {@code float[]} 653 * @param rhs The right-hand side {@code float[]} 654 * @return {@code this} instance. 655 */ 656 public EqualsBuilder append(final float[] lhs, final float[] rhs) { 657 if (!isEquals || lhs == rhs) { 658 return this; 659 } 660 if (lhs == null || rhs == null || lhs.length != rhs.length) { 661 setEquals(false); 662 return this; 663 } 664 for (int i = 0; i < lhs.length && isEquals; ++i) { 665 append(lhs[i], rhs[i]); 666 } 667 return this; 668 } 669 670 /** 671 * Test if two {@code int}s are equal. 672 * 673 * @param lhs The left-hand side {@code int} 674 * @param rhs The right-hand side {@code int} 675 * @return {@code this} instance. 676 */ 677 public EqualsBuilder append(final int lhs, final int rhs) { 678 if (isEquals) { 679 isEquals = lhs == rhs; 680 } 681 return this; 682 } 683 684 /** 685 * Deep comparison of array of {@code int}. Length and all 686 * values are compared. 687 * 688 * <p> 689 * The method {@link #append(int, int)} is used. 690 * </p> 691 * 692 * @param lhs The left-hand side {@code int[]} 693 * @param rhs The right-hand side {@code int[]} 694 * @return {@code this} instance. 695 */ 696 public EqualsBuilder append(final int[] lhs, final int[] rhs) { 697 if (!isEquals || lhs == rhs) { 698 return this; 699 } 700 if (lhs == null || rhs == null || lhs.length != rhs.length) { 701 setEquals(false); 702 return this; 703 } 704 for (int i = 0; i < lhs.length && isEquals; ++i) { 705 append(lhs[i], rhs[i]); 706 } 707 return this; 708 } 709 710 /** 711 * Test if two {@code long}s are equal. 712 * 713 * @param lhs 714 * the left-hand side {@code long} 715 * @param rhs 716 * the right-hand side {@code long} 717 * @return {@code this} instance. 718 */ 719 public EqualsBuilder append(final long lhs, final long rhs) { 720 if (isEquals) { 721 isEquals = lhs == rhs; 722 } 723 return this; 724 } 725 726 /** 727 * Deep comparison of array of {@code long}. Length and all 728 * values are compared. 729 * 730 * <p> 731 * The method {@link #append(long, long)} is used. 732 * </p> 733 * 734 * @param lhs The left-hand side {@code long[]} 735 * @param rhs The right-hand side {@code long[]} 736 * @return {@code this} instance. 737 */ 738 public EqualsBuilder append(final long[] lhs, final long[] rhs) { 739 if (!isEquals || lhs == rhs) { 740 return this; 741 } 742 if (lhs == null || rhs == null || lhs.length != rhs.length) { 743 setEquals(false); 744 return this; 745 } 746 for (int i = 0; i < lhs.length && isEquals; ++i) { 747 append(lhs[i], rhs[i]); 748 } 749 return this; 750 } 751 752 /** 753 * Test if two {@link Object}s are equal using either 754 * #{@link #reflectionAppend(Object, Object)}, if object are non 755 * primitives (or wrapper of primitives) or if field {@code testRecursive} 756 * is set to {@code false}. Otherwise, using their 757 * {@code equals} method. 758 * 759 * @param lhs The left-hand side object 760 * @param rhs The right-hand side object 761 * @return {@code this} instance. 762 */ 763 public EqualsBuilder append(final Object lhs, final Object rhs) { 764 if (!isEquals || lhs == rhs) { 765 return this; 766 } 767 if (lhs == null || rhs == null) { 768 setEquals(false); 769 return this; 770 } 771 final Class<?> lhsClass = lhs.getClass(); 772 if (lhsClass.isArray()) { 773 // factor out array case in order to keep method small enough 774 // to be inlined 775 appendArray(lhs, rhs); 776 } else // The simple case, not an array, just test the element 777 if (testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) { 778 reflectionAppend(lhs, rhs); 779 } else { 780 isEquals = lhs.equals(rhs); 781 } 782 return this; 783 } 784 785 /** 786 * Performs a deep comparison of two {@link Object} arrays. 787 * 788 * <p> 789 * This also will be called for the top level of 790 * multi-dimensional, ragged, and multi-typed arrays. 791 * </p> 792 * 793 * <p> 794 * Note that this method does not compare the type of the arrays; it only 795 * compares the contents. 796 * </p> 797 * 798 * @param lhs The left-hand side {@code Object[]} 799 * @param rhs The right-hand side {@code Object[]} 800 * @return {@code this} instance. 801 */ 802 public EqualsBuilder append(final Object[] lhs, final Object[] rhs) { 803 if (!isEquals || isRegistered(lhs, rhs)) { 804 return this; 805 } 806 try { 807 register(lhs, rhs); 808 if (lhs == rhs) { 809 return this; 810 } 811 if (lhs == null || rhs == null || lhs.length != rhs.length) { 812 setEquals(false); 813 return this; 814 } 815 for (int i = 0; i < lhs.length && isEquals; ++i) { 816 append(lhs[i], rhs[i]); 817 } 818 return this; 819 } finally { 820 unregister(lhs, rhs); 821 } 822 } 823 824 /** 825 * Test if two {@code short}s are equal. 826 * 827 * @param lhs The left-hand side {@code short} 828 * @param rhs The right-hand side {@code short} 829 * @return {@code this} instance. 830 */ 831 public EqualsBuilder append(final short lhs, final short rhs) { 832 if (isEquals) { 833 isEquals = lhs == rhs; 834 } 835 return this; 836 } 837 838 /** 839 * Deep comparison of array of {@code short}. Length and all 840 * values are compared. 841 * 842 * <p> 843 * The method {@link #append(short, short)} is used. 844 * </p> 845 * 846 * @param lhs The left-hand side {@code short[]} 847 * @param rhs The right-hand side {@code short[]} 848 * @return {@code this} instance. 849 */ 850 public EqualsBuilder append(final short[] lhs, final short[] rhs) { 851 if (!isEquals || lhs == rhs) { 852 return this; 853 } 854 if (lhs == null || rhs == null || lhs.length != rhs.length) { 855 setEquals(false); 856 return this; 857 } 858 for (int i = 0; i < lhs.length && isEquals; ++i) { 859 append(lhs[i], rhs[i]); 860 } 861 return this; 862 } 863 864 /** 865 * Test if an {@link Object} is equal to an array. 866 * 867 * @param lhs The left-hand side object, an array 868 * @param rhs The right-hand side object 869 */ 870 private void appendArray(final Object lhs, final Object rhs) { 871 // First we compare different dimensions, for example: a boolean[][] to a boolean[] 872 // then we 'Switch' on type of array, to dispatch to the correct handler 873 // This handles multidimensional arrays of the same depth 874 if (lhs.getClass() != rhs.getClass()) { 875 setEquals(false); 876 } else if (lhs instanceof long[]) { 877 append((long[]) lhs, (long[]) rhs); 878 } else if (lhs instanceof int[]) { 879 append((int[]) lhs, (int[]) rhs); 880 } else if (lhs instanceof short[]) { 881 append((short[]) lhs, (short[]) rhs); 882 } else if (lhs instanceof char[]) { 883 append((char[]) lhs, (char[]) rhs); 884 } else if (lhs instanceof byte[]) { 885 append((byte[]) lhs, (byte[]) rhs); 886 } else if (lhs instanceof double[]) { 887 append((double[]) lhs, (double[]) rhs); 888 } else if (lhs instanceof float[]) { 889 append((float[]) lhs, (float[]) rhs); 890 } else if (lhs instanceof boolean[]) { 891 append((boolean[]) lhs, (boolean[]) rhs); 892 } else { 893 // Not an array of primitives 894 append((Object[]) lhs, (Object[]) rhs); 895 } 896 } 897 898 /** 899 * Adds the result of {@code super.equals()} to this builder. 900 * 901 * @param superEquals The result of calling {@code super.equals()} 902 * @return {@code this} instance. 903 * @since 2.0 904 */ 905 public EqualsBuilder appendSuper(final boolean superEquals) { 906 if (!isEquals) { 907 return this; 908 } 909 isEquals = superEquals; 910 return this; 911 } 912 913 /** 914 * Returns {@code true} if the fields that have been checked 915 * are all equal. 916 * 917 * @return {@code true} if all of the fields that have been checked 918 * are equal, {@code false} otherwise. 919 * 920 * @since 3.0 921 */ 922 @Override 923 public Boolean build() { 924 return Boolean.valueOf(isEquals()); 925 } 926 927 /** 928 * Tests whether all fields checked so far are equal. 929 * 930 * @return boolean 931 */ 932 public boolean isEquals() { 933 return isEquals; 934 } 935 936 /** 937 * Tests if two {@code objects} by using reflection. 938 * 939 * <p> 940 * It uses {@code AccessibleObject.setAccessible} to gain access to private 941 * fields. This means that it will throw a security exception if run under 942 * a security manager, if the permissions are not set up correctly. It is also 943 * not as efficient as testing explicitly. Non-primitive fields are compared using 944 * {@code equals()}. 945 * </p> 946 * 947 * <p> 948 * If the testTransients field is set to {@code true}, transient 949 * members will be tested, otherwise they are ignored, as they are likely 950 * derived fields, and not part of the value of the {@link Object}. 951 * </p> 952 * 953 * <p> 954 * Static fields will not be included. Superclass fields will be appended 955 * up to and including the specified superclass in field {@code reflectUpToClass}. 956 * A null superclass is treated as java.lang.Object. 957 * </p> 958 * 959 * <p> 960 * Field names listed in field {@code excludeFields} will be ignored. 961 * </p> 962 * 963 * <p> 964 * If either class of the compared objects is contained in 965 * {@code bypassReflectionClasses}, both objects are compared by calling 966 * the equals method of the left-hand side object with the right-hand side object as an argument. 967 * </p> 968 * 969 * @param lhs The left-hand side object 970 * @param rhs The right-hand side object 971 * @return {@code this} instance. 972 */ 973 public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) { 974 if (!isEquals || lhs == rhs) { 975 return this; 976 } 977 if (lhs == null || rhs == null) { 978 isEquals = false; 979 return this; 980 } 981 // Find the leaf class since there may be transients in the leaf 982 // class or in classes between the leaf and root. 983 // If we are not testing transients or a subclass has no ivars, 984 // then a subclass can test equals to a superclass. 985 final Class<?> lhsClass = lhs.getClass(); 986 final Class<?> rhsClass = rhs.getClass(); 987 Class<?> testClass; 988 if (lhsClass.isInstance(rhs)) { 989 testClass = lhsClass; 990 if (!rhsClass.isInstance(lhs)) { 991 // rhsClass is a subclass of lhsClass 992 testClass = rhsClass; 993 } 994 } else if (rhsClass.isInstance(lhs)) { 995 testClass = rhsClass; 996 if (!lhsClass.isInstance(rhs)) { 997 // lhsClass is a subclass of rhsClass 998 testClass = lhsClass; 999 } 1000 } else { 1001 // The two classes are not related. 1002 isEquals = false; 1003 return this; 1004 } 1005 try { 1006 if (testClass.isArray()) { 1007 append(lhs, rhs); 1008 } else // If either class is being excluded, call normal object equals method on lhsClass. 1009 if (bypassReflectionClasses != null && (bypassReflectionClasses.contains(lhsClass) || bypassReflectionClasses.contains(rhsClass))) { 1010 isEquals = lhs.equals(rhs); 1011 } else { 1012 reflectionAppend(lhs, rhs, testClass); 1013 while (testClass.getSuperclass() != null && testClass != reflectUpToClass) { 1014 testClass = testClass.getSuperclass(); 1015 reflectionAppend(lhs, rhs, testClass); 1016 } 1017 } 1018 } catch (final IllegalArgumentException e) { 1019 // In this case, we tried to test a subclass vs. a superclass and 1020 // the subclass has ivars or the ivars are transient and 1021 // we are testing transients. 1022 // If a subclass has ivars that we are trying to test them, we get an 1023 // exception and we know that the objects are not equal. 1024 isEquals = false; 1025 } 1026 return this; 1027 } 1028 1029 /** 1030 * Appends the fields and values defined by the given object of the 1031 * given Class. 1032 * 1033 * @param lhs The left-hand side object. 1034 * @param rhs The right-hand side object. 1035 * @param clazz The class to append details of. 1036 */ 1037 private void reflectionAppend(final Object lhs, final Object rhs, final Class<?> clazz) { 1038 if (isRegistered(lhs, rhs)) { 1039 return; 1040 } 1041 try { 1042 register(lhs, rhs); 1043 final Field[] fields = clazz.getDeclaredFields(); 1044 for (int i = 0; i < fields.length && isEquals; i++) { 1045 final Field field = fields[i]; 1046 if (!ArrayUtils.contains(excludeFields, field.getName()) 1047 && !field.getName().contains("$") 1048 && (testTransients || !Modifier.isTransient(field.getModifiers())) 1049 && !Modifier.isStatic(field.getModifiers()) 1050 && !field.isAnnotationPresent(EqualsExclude.class)) { 1051 if (setAccessible(field)) { 1052 append(Reflection.getUnchecked(field, lhs), Reflection.getUnchecked(field, rhs)); 1053 } 1054 } 1055 } 1056 } finally { 1057 unregister(lhs, rhs); 1058 } 1059 } 1060 1061 /** 1062 * Reset the EqualsBuilder so you can use the same object again. 1063 * 1064 * @since 2.5 1065 */ 1066 public void reset() { 1067 isEquals = true; 1068 } 1069 1070 /** 1071 * Sets {@link Class}es whose instances should be compared by calling their {@code equals} 1072 * although being in recursive mode. So the fields of these classes will not be compared recursively by reflection. 1073 * 1074 * <p> 1075 * Here you should name classes having non-transient fields which are cache fields being set lazily.<br> 1076 * Prominent example being {@link String} class with its hash code cache field. Due to the importance 1077 * of the {@link String} class, it is included in the default bypasses classes. Usually, if you use 1078 * your own set of classes here, remember to include {@link String} class, too. 1079 * </p> 1080 * 1081 * @param bypassReflectionClasses classes to bypass reflection test 1082 * @return {@code this} instance. 1083 * @see #setTestRecursive(boolean) 1084 * @since 3.8 1085 */ 1086 public EqualsBuilder setBypassReflectionClasses(final List<Class<?>> bypassReflectionClasses) { 1087 this.bypassReflectionClasses = bypassReflectionClasses; 1088 return this; 1089 } 1090 1091 /** 1092 * Sets the {@code isEquals} value. 1093 * 1094 * @param isEquals The value to set. 1095 * @since 2.1 1096 */ 1097 protected void setEquals(final boolean isEquals) { 1098 this.isEquals = isEquals; 1099 } 1100 1101 /** 1102 * Sets field names to be excluded by reflection tests. 1103 * 1104 * @param excludeFields The fields to exclude 1105 * @return {@code this} instance. 1106 * @since 3.6 1107 */ 1108 public EqualsBuilder setExcludeFields(final String... excludeFields) { 1109 this.excludeFields = excludeFields; 1110 return this; 1111 } 1112 1113 /** 1114 * Sets the superclass to reflect up to at reflective tests. 1115 * 1116 * @param reflectUpToClass The super class to reflect up to 1117 * @return {@code this} instance. 1118 * @since 3.6 1119 */ 1120 public EqualsBuilder setReflectUpToClass(final Class<?> reflectUpToClass) { 1121 this.reflectUpToClass = reflectUpToClass; 1122 return this; 1123 } 1124 1125 /** 1126 * Sets whether to test fields recursively, instead of using their equals method, when reflectively comparing objects. 1127 * String objects, which cache a hash value, are automatically excluded from recursive testing. 1128 * You may specify other exceptions by calling {@link #setBypassReflectionClasses(List)}. 1129 * 1130 * <p> 1131 * Cycle protection is a visit stack, not a visited set: shared (acyclic) references are 1132 * re-compared on every path, so deeply nested graphs with many shared references can be 1133 * exponentially expensive to compare. Avoid on object graphs built from untrusted input. 1134 * </p> 1135 * 1136 * @param testRecursive whether to do a recursive test 1137 * @return {@code this} instance. 1138 * @see #setBypassReflectionClasses(List) 1139 * @since 3.6 1140 */ 1141 public EqualsBuilder setTestRecursive(final boolean testRecursive) { 1142 this.testRecursive = testRecursive; 1143 return this; 1144 } 1145 1146 /** 1147 * Sets whether to include transient fields when reflectively comparing objects. 1148 * 1149 * @param testTransients whether to test transient fields 1150 * @return {@code this} instance. 1151 * @since 3.6 1152 */ 1153 public EqualsBuilder setTestTransients(final boolean testTransients) { 1154 this.testTransients = testTransients; 1155 return this; 1156 } 1157}