View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.builder;
18  
19  import java.lang.reflect.Field;
20  import java.lang.reflect.Modifier;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.commons.lang3.ArrayUtils;
28  import org.apache.commons.lang3.ClassUtils;
29  import org.apache.commons.lang3.tuple.Pair;
30  
31  /**
32   * Assists in implementing {@link Object#equals(Object)} methods.
33   *
34   * <p>
35   * This class provides methods to build a good equals method for any
36   * class. It follows rules laid out in
37   * <a href="https://www.oracle.com/java/technologies/effectivejava.html">Effective Java</a>
38   * , by Joshua Bloch. In particular the rule for comparing {@code doubles},
39   * {@code floats}, and arrays can be tricky. Also, making sure that
40   * {@code equals()} and {@code hashCode()} are consistent can be
41   * difficult.
42   * </p>
43   *
44   * <p>
45   * Two Objects that compare as equals must generate the same hash code,
46   * but two Objects with the same hash code do not have to be equal.
47   * </p>
48   *
49   * <p>
50   * All relevant fields should be included in the calculation of equals.
51   * Derived fields may be ignored. In particular, any field used in
52   * generating a hash code must be used in the equals method, and vice
53   * versa.
54   * </p>
55   *
56   * <p>
57   * Typical use for the code is as follows:
58   * </p>
59   * <pre>
60   * public boolean equals(Object obj) {
61   *   if (obj == null) { return false; }
62   *   if (obj == this) { return true; }
63   *   if (obj.getClass() != getClass()) {
64   *     return false;
65   *   }
66   *   MyClass rhs = (MyClass) obj;
67   *   return new EqualsBuilder()
68   *                 .appendSuper(super.equals(obj))
69   *                 .append(field1, rhs.field1)
70   *                 .append(field2, rhs.field2)
71   *                 .append(field3, rhs.field3)
72   *                 .isEquals();
73   *  }
74   * </pre>
75   *
76   * <p>
77   * Alternatively, there is a method that uses reflection to determine
78   * the fields to test. Because these fields are usually private, the method,
79   * {@code reflectionEquals}, uses {@code AccessibleObject.setAccessible} to
80   * change the visibility of the fields. This will fail under a security
81   * manager, unless the appropriate permissions are set up correctly. It is
82   * also slower than testing explicitly.  Non-primitive fields are compared using
83   * {@code equals()}.
84   * </p>
85   * <p>
86   * See also {@link AbstractBuilder#setForceAccessible(boolean)}
87   * </p>
88   *
89   * <p>
90   * A typical invocation for this method would look like:
91   * </p>
92   * <pre>
93   * public boolean equals(Object obj) {
94   *   return EqualsBuilder.reflectionEquals(this, obj);
95   * }
96   * </pre>
97   *
98   * <p>
99   * 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  */
106 public 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 }