public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass,
            final String... excludeFields) {
        if (lhs == rhs) {
            return true;
        }
        if (lhs == null || rhs == null) {
            return false;
        }
        // Find the leaf class since there may be transients in the leaf
        // class or in classes between the leaf and root.
        // If we are not testing transients or a subclass has no ivars,
        // then a subclass can test equals to a superclass.
        final Class<?> lhsClass = lhs.getClass();
        final Class<?> rhsClass = rhs.getClass();
        Class<?> testClass;
        if (lhsClass.isInstance(rhs)) {
            testClass = lhsClass;
            if (!rhsClass.isInstance(lhs)) {
                // rhsClass is a subclass of lhsClass
                testClass = rhsClass;
            }
        } else if (rhsClass.isInstance(lhs)) {
            testClass = rhsClass;
            if (!lhsClass.isInstance(rhs)) {
                // lhsClass is a subclass of rhsClass
                testClass = lhsClass;
            }
        } else {
            // The two classes are not related.
            return false;
        }
        final EqualsBuilder equalsBuilder = new EqualsBuilder();
        try {
            if (testClass.isArray()) {
                equalsBuilder.append(lhs, rhs);
            } else {
                reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
                while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
                    testClass = testClass.getSuperclass();
                    reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields);
                }
            }
        } catch (final IllegalArgumentException e) {
            // In this case, we tried to test a subclass vs. a superclass and
            // the subclass has ivars or the ivars are transient and
            // we are testing transients.
            // If a subclass has ivars that we are trying to test them, we get an
            // exception and we know that the objects are not equal.
            return false;
        }
        return equalsBuilder.isEquals();
    }
public static boolean reflectionEquals ( final Object lhs , final Object rhs , final boolean testTransients , final Class < ? > reflectUpToClass , final String ... excludeFields ) { if ( lhs == rhs ) { return true ; } if ( lhs == null || rhs == null ) { return false ; } final Class < ? > lhsClass = lhs . getClass ( ) ; final Class < ? > rhsClass = rhs . getClass ( ) ; Class < ? > testClass ; if ( lhsClass . isInstance ( rhs ) ) { testClass = lhsClass ; if ( ! rhsClass . isInstance ( lhs ) ) { testClass = rhsClass ; } } else if ( rhsClass . isInstance ( lhs ) ) { testClass = rhsClass ; if ( ! lhsClass . isInstance ( rhs ) ) { testClass = lhsClass ; } } else { return false ; } final EqualsBuilder equalsBuilder = new EqualsBuilder ( ) ; try { if ( testClass . isArray ( ) ) { equalsBuilder . append ( lhs , rhs ) ; } else { reflectionAppend ( lhs , rhs , testClass , equalsBuilder , testTransients , excludeFields ) ; while ( testClass . getSuperclass ( ) != null && testClass != reflectUpToClass ) { testClass = testClass . getSuperclass ( ) ; reflectionAppend ( lhs , rhs , testClass , equalsBuilder , testTransients , excludeFields ) ; } } } catch ( final IllegalArgumentException e ) { return false ; } return equalsBuilder . isEquals ( ) ; }
<p>This method uses reflection to determine if the two <code>Object</code>s
are equal.</p>

<p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
fields. This means that it will throw a security exception if run under
a security manager, if the permissions are not set up correctly. It is also
not as efficient as testing explicitly. Non-primitive fields are compared using
<code>equals()</code>.</p>

<p>If the testTransients parameter is set to <code>true</code>, transient
members will be tested, otherwise they are ignored, as they are likely
derived fields, and not part of the value of the <code>Object</code>.</p>

<p>Static fields will not be included. Superclass fields will be appended
up to and including the specified superclass. A null superclass is treated
as java.lang.Object.</p>

@param lhs  <code>this</code> object
@param rhs  the other object
@param testTransients  whether to include transient fields
@param reflectUpToClass  the superclass to reflect up to (inclusive),
may be <code>null</code>
@param excludeFields  array of field names to exclude from testing
@return <code>true</code> if the two Objects have tested equals.
@since 2.0