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