There must be something messed up with EOLs despite my git autocrlf
settings... sorry about that.

Gary

On Wed, Jul 12, 2023, 08:51 Gilles Sadowski <gillese...@gmail.com> wrote:

> Hi.
>
> Le mer. 12 juil. 2023 à 14:44, <ggreg...@apache.org> a écrit :
> >
> > This is an automated email from the ASF dual-hosted git repository.
> >
> > ggregory pushed a commit to branch master
> > in repository https://gitbox.apache.org/repos/asf/commons-lang.git
> >
> > commit 2e3feda04337baa483bc26b66f238161dc6c97ac
> > Author: Gary Gregory <garydgreg...@gmail.com>
> > AuthorDate: Wed Jul 12 08:44:38 2023 -0400
> >
> >     Throw IllegalArgumentException instead of InternalError in the
> builder
> >     package
>
> The diff below contains a bunch of (formatting ?) changes that
> have nothing to do with this commit message.
>
> Regards,
> Gilles
>
> > ---
> >  src/changes/changes.xml                            |   1 +
> >  .../commons/lang3/builder/CompareToBuilder.java    | 752
> ++++++++++-----------
> >  .../commons/lang3/builder/EqualsBuilder.java       |  20 +-
> >  .../commons/lang3/builder/HashCodeBuilder.java     |   9 +-
> >  .../apache/commons/lang3/builder/Reflection.java   |  44 ++
> >  .../lang3/builder/ReflectionDiffBuilder.java       |   7 +-
> >  .../lang3/builder/ReflectionToStringBuilder.java   |  14 +-
> >  7 files changed, 434 insertions(+), 413 deletions(-)
> >
> > diff --git a/src/changes/changes.xml b/src/changes/changes.xml
> > index 26d7be48c..da3522029 100644
> > --- a/src/changes/changes.xml
> > +++ b/src/changes/changes.xml
> > @@ -123,6 +123,7 @@ The <action> type attribute can be
> add,update,fix,remove.
> >      <action                   type="fix" dev="ggregory"
> due-to="Dimitrios Efthymiou">Update Javadoc for the insert methods in
> ArrayUtils #1078.</action>
> >      <action                   type="fix" dev="ggregory" due-to="Gary
> Gregory">Deprecate ExceptionUtils.ExceptionUtils().</action>
> >      <action issue="LANG-1697" type="fix" dev="ggregory" due-to="Jan
> Arne Sparka, Gary Gregory">TypeUtils.getRawType() throws a
> NullPointerException on Wildcard GenericArrayType.</action>
> > +    <action                   type="fix" dev="ggregory" due-to="Gary
> Gregory">Throw IllegalArgumentException instead of InternalError in the
> builder package.</action>
> >      <!-- ADD -->
> >      <action                   type="add" dev="ggregory" due-to="Gary
> Gregory">Add GitHub coverage.yml.</action>
> >      <action                   type="add" dev="ggregory" due-to="Gary
> Gregory">Add EnumUtils.getEnumSystemProperty(...).</action>
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
> b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
> > index 38c69e613..3d411bb15 100644
> > ---
> a/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
> > +++
> b/src/main/java/org/apache/commons/lang3/builder/CompareToBuilder.java
> > @@ -97,19 +97,37 @@ import org.apache.commons.lang3.ObjectUtils;
> >  public class CompareToBuilder implements Builder<Integer> {
> >
> >      /**
> > -     * Current state of the comparison as appended fields are checked.
> > -     */
> > -    private int comparison;
> > -
> > -    /**
> > -     * Constructor for CompareToBuilder.
> > +     * Appends to {@code builder} the comparison of {@code lhs}
> > +     * to {@code rhs} using the fields defined in {@code clazz}.
> >       *
> > -     * <p>Starts off assuming that the objects are equal. Multiple
> calls are
> > -     * then made to the various append methods, followed by a call to
> > -     * {@link #toComparison} to get the result.</p>
> > +     * @param lhs  left-hand object
> > +     * @param rhs  right-hand object
> > +     * @param clazz  {@link Class} that defines fields to be compared
> > +     * @param builder  {@link CompareToBuilder} to append to
> > +     * @param useTransients  whether to compare transient fields
> > +     * @param excludeFields  fields to exclude
> >       */
> > -    public CompareToBuilder() {
> > -        comparison = 0;
> > +    private static void reflectionAppend(
> > +        final Object lhs,
> > +        final Object rhs,
> > +        final Class<?> clazz,
> > +        final CompareToBuilder builder,
> > +        final boolean useTransients,
> > +        final String[] excludeFields) {
> > +
> > +        final Field[] fields = clazz.getDeclaredFields();
> > +        AccessibleObject.setAccessible(fields, true);
> > +        for (int i = 0; i < fields.length && builder.comparison == 0;
> i++) {
> > +            final Field field = fields[i];
> > +            if (!ArrayUtils.contains(excludeFields, field.getName())
> > +                && !field.getName().contains("$")
> > +                && (useTransients ||
> !Modifier.isTransient(field.getModifiers()))
> > +                && !Modifier.isStatic(field.getModifiers())) {
> > +                // IllegalAccessException can't happen. Would get a
> Security exception instead.
> > +                // Throw a runtime exception in case the impossible
> happens.
> > +                builder.append(Reflection.getUnchecked(field, lhs),
> Reflection.getUnchecked(field, rhs));
> > +            }
> > +        }
> >      }
> >
> >      /**
> > @@ -183,10 +201,11 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *
> >       * <ul>
> >       * <li>Static fields will not be compared</li>
> > -     * <li>If {@code compareTransients} is {@code true},
> > +     * <li>If the {@code compareTransients} is {@code true},
> >       *     compares transient members.  Otherwise ignores them, as they
> >       *     are likely derived fields.</li>
> > -     * <li>Superclass fields will be compared</li>
> > +     * <li>Compares superclass fields up to and including {@code
> reflectUpToClass}.
> > +     *     If {@code reflectUpToClass} is {@code null}, compares all
> superclass fields.</li>
> >       * </ul>
> >       *
> >       * <p>If both {@code lhs} and {@code rhs} are {@code null},
> > @@ -194,17 +213,41 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *
> >       * @param lhs  left-hand object
> >       * @param rhs  right-hand object
> > -     * @param excludeFields  Collection of String fields to exclude
> > +     * @param compareTransients  whether to compare transient fields
> > +     * @param reflectUpToClass  last superclass for which fields are
> compared
> > +     * @param excludeFields  fields to exclude
> >       * @return a negative integer, zero, or a positive integer as
> {@code lhs}
> >       *  is less than, equal to, or greater than {@code rhs}
> >       * @throws NullPointerException  if either {@code lhs} or {@code
> rhs}
> >       *  (but not both) is {@code null}
> >       * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> >       *  with {@code lhs}
> > -     * @since 2.2
> > +     * @since 2.2 (2.0 as {@code reflectionCompare(Object, Object,
> boolean, Class)})
> >       */
> > -    public static int reflectionCompare(final Object lhs, final Object
> rhs, final Collection<String> excludeFields) {
> > -        return reflectionCompare(lhs, rhs,
> ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
> > +    public static int reflectionCompare(
> > +        final Object lhs,
> > +        final Object rhs,
> > +        final boolean compareTransients,
> > +        final Class<?> reflectUpToClass,
> > +        final String... excludeFields) {
> > +
> > +        if (lhs == rhs) {
> > +            return 0;
> > +        }
> > +        Objects.requireNonNull(lhs, "lhs");
> > +        Objects.requireNonNull(rhs, "rhs");
> > +
> > +        Class<?> lhsClazz = lhs.getClass();
> > +        if (!lhsClazz.isInstance(rhs)) {
> > +            throw new ClassCastException();
> > +        }
> > +        final CompareToBuilder compareToBuilder = new
> CompareToBuilder();
> > +        reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder,
> compareTransients, excludeFields);
> > +        while (lhsClazz.getSuperclass() != null && lhsClazz !=
> reflectUpToClass) {
> > +            lhsClazz = lhsClazz.getSuperclass();
> > +            reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder,
> compareTransients, excludeFields);
> > +        }
> > +        return compareToBuilder.toComparison();
> >      }
> >
> >      /**
> > @@ -227,7 +270,7 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *
> >       * @param lhs  left-hand object
> >       * @param rhs  right-hand object
> > -     * @param excludeFields  array of fields to exclude
> > +     * @param excludeFields  Collection of String fields to exclude
> >       * @return a negative integer, zero, or a positive integer as
> {@code lhs}
> >       *  is less than, equal to, or greater than {@code rhs}
> >       * @throws NullPointerException  if either {@code lhs} or {@code
> rhs}
> > @@ -236,8 +279,8 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *  with {@code lhs}
> >       * @since 2.2
> >       */
> > -    public static int reflectionCompare(final Object lhs, final Object
> rhs, final String... excludeFields) {
> > -        return reflectionCompare(lhs, rhs, false, null, excludeFields);
> > +    public static int reflectionCompare(final Object lhs, final Object
> rhs, final Collection<String> excludeFields) {
> > +        return reflectionCompare(lhs, rhs,
> ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
> >      }
> >
> >      /**
> > @@ -249,11 +292,10 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *
> >       * <ul>
> >       * <li>Static fields will not be compared</li>
> > -     * <li>If the {@code compareTransients} is {@code true},
> > +     * <li>If {@code compareTransients} is {@code true},
> >       *     compares transient members.  Otherwise ignores them, as they
> >       *     are likely derived fields.</li>
> > -     * <li>Compares superclass fields up to and including {@code
> reflectUpToClass}.
> > -     *     If {@code reflectUpToClass} is {@code null}, compares all
> superclass fields.</li>
> > +     * <li>Superclass fields will be compared</li>
> >       * </ul>
> >       *
> >       * <p>If both {@code lhs} and {@code rhs} are {@code null},
> > @@ -261,146 +303,74 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >       *
> >       * @param lhs  left-hand object
> >       * @param rhs  right-hand object
> > -     * @param compareTransients  whether to compare transient fields
> > -     * @param reflectUpToClass  last superclass for which fields are
> compared
> > -     * @param excludeFields  fields to exclude
> > +     * @param excludeFields  array of fields to exclude
> >       * @return a negative integer, zero, or a positive integer as
> {@code lhs}
> >       *  is less than, equal to, or greater than {@code rhs}
> >       * @throws NullPointerException  if either {@code lhs} or {@code
> rhs}
> >       *  (but not both) is {@code null}
> >       * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> >       *  with {@code lhs}
> > -     * @since 2.2 (2.0 as {@code reflectionCompare(Object, Object,
> boolean, Class)})
> > +     * @since 2.2
> >       */
> > -    public static int reflectionCompare(
> > -        final Object lhs,
> > -        final Object rhs,
> > -        final boolean compareTransients,
> > -        final Class<?> reflectUpToClass,
> > -        final String... excludeFields) {
> > -
> > -        if (lhs == rhs) {
> > -            return 0;
> > -        }
> > -        Objects.requireNonNull(lhs, "lhs");
> > -        Objects.requireNonNull(rhs, "rhs");
> > -
> > -        Class<?> lhsClazz = lhs.getClass();
> > -        if (!lhsClazz.isInstance(rhs)) {
> > -            throw new ClassCastException();
> > -        }
> > -        final CompareToBuilder compareToBuilder = new
> CompareToBuilder();
> > -        reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder,
> compareTransients, excludeFields);
> > -        while (lhsClazz.getSuperclass() != null && lhsClazz !=
> reflectUpToClass) {
> > -            lhsClazz = lhsClazz.getSuperclass();
> > -            reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder,
> compareTransients, excludeFields);
> > -        }
> > -        return compareToBuilder.toComparison();
> > +    public static int reflectionCompare(final Object lhs, final Object
> rhs, final String... excludeFields) {
> > +        return reflectionCompare(lhs, rhs, false, null, excludeFields);
> >      }
> >
> >      /**
> > -     * Appends to {@code builder} the comparison of {@code lhs}
> > -     * to {@code rhs} using the fields defined in {@code clazz}.
> > -     *
> > -     * @param lhs  left-hand object
> > -     * @param rhs  right-hand object
> > -     * @param clazz  {@link Class} that defines fields to be compared
> > -     * @param builder  {@link CompareToBuilder} to append to
> > -     * @param useTransients  whether to compare transient fields
> > -     * @param excludeFields  fields to exclude
> > +     * Current state of the comparison as appended fields are checked.
> >       */
> > -    private static void reflectionAppend(
> > -        final Object lhs,
> > -        final Object rhs,
> > -        final Class<?> clazz,
> > -        final CompareToBuilder builder,
> > -        final boolean useTransients,
> > -        final String[] excludeFields) {
> > -
> > -        final Field[] fields = clazz.getDeclaredFields();
> > -        AccessibleObject.setAccessible(fields, true);
> > -        for (int i = 0; i < fields.length && builder.comparison == 0;
> i++) {
> > -            final Field field = fields[i];
> > -            if (!ArrayUtils.contains(excludeFields, field.getName())
> > -                && !field.getName().contains("$")
> > -                && (useTransients ||
> !Modifier.isTransient(field.getModifiers()))
> > -                && !Modifier.isStatic(field.getModifiers())) {
> > -                try {
> > -                    builder.append(field.get(lhs), field.get(rhs));
> > -                } catch (final IllegalAccessException e) {
> > -                    // This can't happen. Would get a Security
> exception instead.
> > -                    // Throw a runtime exception in case the impossible
> happens.
> > -                    throw new InternalError("Unexpected
> IllegalAccessException");
> > -                }
> > -            }
> > -        }
> > -    }
> > +    private int comparison;
> >
> >      /**
> > -     * Appends to the {@code builder} the {@code compareTo(Object)}
> > -     * result of the superclass.
> > +     * Constructor for CompareToBuilder.
> >       *
> > -     * @param superCompareTo  result of calling {@code
> super.compareTo(Object)}
> > -     * @return this
> > -     * @since 2.0
> > +     * <p>Starts off assuming that the objects are equal. Multiple
> calls are
> > +     * then made to the various append methods, followed by a call to
> > +     * {@link #toComparison} to get the result.</p>
> >       */
> > -    public CompareToBuilder appendSuper(final int superCompareTo) {
> > -        if (comparison != 0) {
> > -            return this;
> > -        }
> > -        comparison = superCompareTo;
> > -        return this;
> > +    public CompareToBuilder() {
> > +        comparison = 0;
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the comparison of
> > -     * two {@link Object}s.
> > -     *
> > -     * <ol>
> > -     * <li>Check if {@code lhs == rhs}</li>
> > -     * <li>Check if either {@code lhs} or {@code rhs} is {@code null},
> > -     *     a {@code null} object is less than a non-{@code null}
> object</li>
> > -     * <li>Check the object contents</li>
> > -     * </ol>
> > -     *
> > -     * <p>{@code lhs} must either be an array or implement {@link
> Comparable}.</p>
> > +     * two {@code booleans}s.
> >       *
> > -     * @param lhs  left-hand object
> > -     * @param rhs  right-hand object
> > +     * @param lhs  left-hand value
> > +     * @param rhs  right-hand value
> >       * @return this
> > -     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > -     *  with {@code lhs}
> > -     */
> > -    public CompareToBuilder append(final Object lhs, final Object rhs) {
> > -        return append(lhs, rhs, null);
> > +      */
> > +    public CompareToBuilder append(final boolean lhs, final boolean
> rhs) {
> > +        if (comparison != 0) {
> > +            return this;
> > +        }
> > +        if (lhs == rhs) {
> > +            return this;
> > +        }
> > +        if (lhs) {
> > +            comparison = 1;
> > +        } else {
> > +            comparison = -1;
> > +        }
> > +        return this;
> >      }
> >
> >      /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@link Object}s.
> > +     * Appends to the {@code builder} the deep comparison of
> > +     * two {@code boolean} arrays.
> >       *
> >       * <ol>
> > -     * <li>Check if {@code lhs == rhs}</li>
> > -     * <li>Check if either {@code lhs} or {@code rhs} is {@code null},
> > -     *     a {@code null} object is less than a non-{@code null}
> object</li>
> > -     * <li>Check the object contents</li>
> > +     *  <li>Check if arrays are the same using {@code ==}</li>
> > +     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > +     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(boolean, boolean)}</li>
> >       * </ol>
> >       *
> > -     * <p>If {@code lhs} is an array, array comparison methods will be
> used.
> > -     * Otherwise {@code comparator} will be used to compare the objects.
> > -     * If {@code comparator} is {@code null}, {@code lhs} must
> > -     * implement {@link Comparable} instead.</p>
> > -     *
> > -     * @param lhs  left-hand object
> > -     * @param rhs  right-hand object
> > -     * @param comparator  {@link Comparator} used to compare the
> objects,
> > -     *  {@code null} means treat lhs as {@link Comparable}
> > +     * @param lhs  left-hand array
> > +     * @param rhs  right-hand array
> >       * @return this
> > -     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > -     *  with {@code lhs}
> > -     * @since 2.0
> >       */
> > -    public CompareToBuilder append(final Object lhs, final Object rhs,
> final Comparator<?> comparator) {
> > +    public CompareToBuilder append(final boolean[] lhs, final boolean[]
> rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -415,94 +385,69 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >              comparison = 1;
> >              return this;
> >          }
> > -        if (ObjectUtils.isArray(lhs)) {
> > -            // factor out array case in order to keep method small
> enough to be inlined
> > -            appendArray(lhs, rhs, comparator);
> > -        } else // the simple case, not an array, just test the element
> > -        if (comparator == null) {
> > -            @SuppressWarnings("unchecked") // assume this can be done;
> if not throw CCE as per Javadoc
> > -            final Comparable<Object> comparable = (Comparable<Object>)
> lhs;
> > -            comparison = comparable.compareTo(rhs);
> > -        } else {
> > -            @SuppressWarnings("unchecked") // assume this can be done;
> if not throw CCE as per Javadoc
> > -            final Comparator<Object> comparator2 = (Comparator<Object>)
> comparator;
> > -            comparison = comparator2.compare(lhs, rhs);
> > +        if (lhs.length != rhs.length) {
> > +            comparison = lhs.length < rhs.length ? -1 : 1;
> > +            return this;
> >          }
> > -        return this;
> > -    }
> > -
> > -    private void appendArray(final Object lhs, final Object rhs, final
> Comparator<?> comparator) {
> > -        // switch on type of array, to dispatch to the correct handler
> > -        // handles multidimensional arrays
> > -        // throws a ClassCastException if rhs is not the correct array
> type
> > -        if (lhs instanceof long[]) {
> > -            append((long[]) lhs, (long[]) rhs);
> > -        } else if (lhs instanceof int[]) {
> > -            append((int[]) lhs, (int[]) rhs);
> > -        } else if (lhs instanceof short[]) {
> > -            append((short[]) lhs, (short[]) rhs);
> > -        } else if (lhs instanceof char[]) {
> > -            append((char[]) lhs, (char[]) rhs);
> > -        } else if (lhs instanceof byte[]) {
> > -            append((byte[]) lhs, (byte[]) rhs);
> > -        } else if (lhs instanceof double[]) {
> > -            append((double[]) lhs, (double[]) rhs);
> > -        } else if (lhs instanceof float[]) {
> > -            append((float[]) lhs, (float[]) rhs);
> > -        } else if (lhs instanceof boolean[]) {
> > -            append((boolean[]) lhs, (boolean[]) rhs);
> > -        } else {
> > -            // not an array of primitives
> > -            // throws a ClassCastException if rhs is not an array
> > -            append((Object[]) lhs, (Object[]) rhs, comparator);
> > +        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > +            append(lhs[i], rhs[i]);
> >          }
> > +        return this;
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the comparison of
> > -     * two {@code long}s.
> > +     * two {@code byte}s.
> >       *
> >       * @param lhs  left-hand value
> >       * @param rhs  right-hand value
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final long lhs, final long rhs) {
> > +    public CompareToBuilder append(final byte lhs, final byte rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > -        comparison = Long.compare(lhs, rhs);
> > +        comparison = Byte.compare(lhs, rhs);
> >          return this;
> >      }
> >
> >      /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@code int}s.
> > +     * Appends to the {@code builder} the deep comparison of
> > +     * two {@code byte} arrays.
> >       *
> > -     * @param lhs  left-hand value
> > -     * @param rhs  right-hand value
> > +     * <ol>
> > +     *  <li>Check if arrays are the same using {@code ==}</li>
> > +     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > +     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(byte, byte)}</li>
> > +     * </ol>
> > +     *
> > +     * @param lhs  left-hand array
> > +     * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final int lhs, final int rhs) {
> > +    public CompareToBuilder append(final byte[] lhs, final byte[] rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > -        comparison = Integer.compare(lhs, rhs);
> > -        return this;
> > -    }
> > -
> > -    /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@code short}s.
> > -     *
> > -     * @param lhs  left-hand value
> > -     * @param rhs  right-hand value
> > -     * @return this
> > -     */
> > -    public CompareToBuilder append(final short lhs, final short rhs) {
> > -        if (comparison != 0) {
> > +        if (lhs == rhs) {
> >              return this;
> >          }
> > -        comparison = Short.compare(lhs, rhs);
> > +        if (lhs == null) {
> > +            comparison = -1;
> > +            return this;
> > +        }
> > +        if (rhs == null) {
> > +            comparison = 1;
> > +            return this;
> > +        }
> > +        if (lhs.length != rhs.length) {
> > +            comparison = lhs.length < rhs.length ? -1 : 1;
> > +            return this;
> > +        }
> > +        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > +            append(lhs[i], rhs[i]);
> > +        }
> >          return this;
> >      }
> >
> > @@ -523,18 +468,42 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >      }
> >
> >      /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@code byte}s.
> > +     * Appends to the {@code builder} the deep comparison of
> > +     * two {@code char} arrays.
> >       *
> > -     * @param lhs  left-hand value
> > -     * @param rhs  right-hand value
> > +     * <ol>
> > +     *  <li>Check if arrays are the same using {@code ==}</li>
> > +     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > +     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(char, char)}</li>
> > +     * </ol>
> > +     *
> > +     * @param lhs  left-hand array
> > +     * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final byte lhs, final byte rhs) {
> > +    public CompareToBuilder append(final char[] lhs, final char[] rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > -        comparison = Byte.compare(lhs, rhs);
> > +        if (lhs == rhs) {
> > +            return this;
> > +        }
> > +        if (lhs == null) {
> > +            comparison = -1;
> > +            return this;
> > +        }
> > +        if (rhs == null) {
> > +            comparison = 1;
> > +            return this;
> > +        }
> > +        if (lhs.length != rhs.length) {
> > +            comparison = lhs.length < rhs.length ? -1 : 1;
> > +            return this;
> > +        }
> > +        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > +            append(lhs[i], rhs[i]);
> > +        }
> >          return this;
> >      }
> >
> > @@ -559,98 +528,22 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >          return this;
> >      }
> >
> > -    /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@code float}s.
> > -     *
> > -     * <p>This handles NaNs, Infinities, and {@code -0.0}.</p>
> > -     *
> > -     * <p>It is compatible with the hash code generated by
> > -     * {@link HashCodeBuilder}.</p>
> > -     *
> > -     * @param lhs  left-hand value
> > -     * @param rhs  right-hand value
> > -     * @return this
> > -     */
> > -    public CompareToBuilder append(final float lhs, final float rhs) {
> > -        if (comparison != 0) {
> > -            return this;
> > -        }
> > -        comparison = Float.compare(lhs, rhs);
> > -        return this;
> > -    }
> > -
> > -    /**
> > -     * Appends to the {@code builder} the comparison of
> > -     * two {@code booleans}s.
> > -     *
> > -     * @param lhs  left-hand value
> > -     * @param rhs  right-hand value
> > -     * @return this
> > -      */
> > -    public CompareToBuilder append(final boolean lhs, final boolean
> rhs) {
> > -        if (comparison != 0) {
> > -            return this;
> > -        }
> > -        if (lhs == rhs) {
> > -            return this;
> > -        }
> > -        if (lhs) {
> > -            comparison = 1;
> > -        } else {
> > -            comparison = -1;
> > -        }
> > -        return this;
> > -    }
> > -
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@link Object} arrays.
> > -     *
> > -     * <ol>
> > -     *  <li>Check if arrays are the same using {@code ==}</li>
> > -     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a short length array is less than a
> long length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(Object, Object, Comparator)}</li>
> > -     * </ol>
> > -     *
> > -     * <p>This method will also will be called for the top level of
> multi-dimensional,
> > -     * ragged, and multi-typed arrays.</p>
> > -     *
> > -     * @param lhs  left-hand array
> > -     * @param rhs  right-hand array
> > -     * @return this
> > -     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > -     *  with {@code lhs}
> > -     */
> > -    public CompareToBuilder append(final Object[] lhs, final Object[]
> rhs) {
> > -        return append(lhs, rhs, null);
> > -    }
> > -
> > -    /**
> > -     * Appends to the {@code builder} the deep comparison of
> > -     * two {@link Object} arrays.
> > +     * two {@code double} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a short length array is less than a
> long length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(Object, Object, Comparator)}</li>
> > +     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(double, double)}</li>
> >       * </ol>
> >       *
> > -     * <p>This method will also will be called for the top level of
> multi-dimensional,
> > -     * ragged, and multi-typed arrays.</p>
> > -     *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> > -     * @param comparator  {@link Comparator} to use to compare the
> array elements,
> > -     *  {@code null} means to treat {@code lhs} elements as {@link
> Comparable}.
> >       * @return this
> > -     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > -     *  with {@code lhs}
> > -     * @since 2.0
> >       */
> > -    public CompareToBuilder append(final Object[] lhs, final Object[]
> rhs, final Comparator<?> comparator) {
> > +    public CompareToBuilder append(final double[] lhs, final double[]
> rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -670,67 +563,48 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >              return this;
> >          }
> >          for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > -            append(lhs[i], rhs[i], comparator);
> > +            append(lhs[i], rhs[i]);
> >          }
> >          return this;
> >      }
> >
> >      /**
> > -     * Appends to the {@code builder} the deep comparison of
> > -     * two {@code long} arrays.
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@code float}s.
> >       *
> > -     * <ol>
> > -     *  <li>Check if arrays are the same using {@code ==}</li>
> > -     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(long, long)}</li>
> > -     * </ol>
> > +     * <p>This handles NaNs, Infinities, and {@code -0.0}.</p>
> >       *
> > -     * @param lhs  left-hand array
> > -     * @param rhs  right-hand array
> > +     * <p>It is compatible with the hash code generated by
> > +     * {@link HashCodeBuilder}.</p>
> > +     *
> > +     * @param lhs  left-hand value
> > +     * @param rhs  right-hand value
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final long[] lhs, final long[] rhs) {
> > +    public CompareToBuilder append(final float lhs, final float rhs) {
> >          if (comparison != 0) {
> > -            return this;
> > -        }
> > -        if (lhs == rhs) {
> > -            return this;
> > -        }
> > -        if (lhs == null) {
> > -            comparison = -1;
> > -            return this;
> > -        }
> > -        if (rhs == null) {
> > -            comparison = 1;
> > -            return this;
> > -        }
> > -        if (lhs.length != rhs.length) {
> > -            comparison = lhs.length < rhs.length ? -1 : 1;
> > -            return this;
> > -        }
> > -        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > -            append(lhs[i], rhs[i]);
> > +            return this;
> >          }
> > +        comparison = Float.compare(lhs, rhs);
> >          return this;
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code int} arrays.
> > +     * two {@code float} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> >       *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(int, int)}</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(float, float)}</li>
> >       * </ol>
> >       *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final int[] lhs, final int[] rhs) {
> > +    public CompareToBuilder append(final float[] lhs, final float[]
> rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -755,22 +629,38 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >          return this;
> >      }
> >
> > +    /**
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@code int}s.
> > +     *
> > +     * @param lhs  left-hand value
> > +     * @param rhs  right-hand value
> > +     * @return this
> > +     */
> > +    public CompareToBuilder append(final int lhs, final int rhs) {
> > +        if (comparison != 0) {
> > +            return this;
> > +        }
> > +        comparison = Integer.compare(lhs, rhs);
> > +        return this;
> > +    }
> > +
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code short} arrays.
> > +     * two {@code int} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> >       *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(short, short)}</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(int, int)}</li>
> >       * </ol>
> >       *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final short[] lhs, final short[]
> rhs) {
> > +    public CompareToBuilder append(final int[] lhs, final int[] rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -795,22 +685,38 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >          return this;
> >      }
> >
> > +    /**
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@code long}s.
> > +     *
> > +     * @param lhs  left-hand value
> > +     * @param rhs  right-hand value
> > +     * @return this
> > +     */
> > +    public CompareToBuilder append(final long lhs, final long rhs) {
> > +        if (comparison != 0) {
> > +            return this;
> > +        }
> > +        comparison = Long.compare(lhs, rhs);
> > +        return this;
> > +    }
> > +
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code char} arrays.
> > +     * two {@code long} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> >       *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(char, char)}</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(long, long)}</li>
> >       * </ol>
> >       *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final char[] lhs, final char[] rhs) {
> > +    public CompareToBuilder append(final long[] lhs, final long[] rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -836,21 +742,54 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >      }
> >
> >      /**
> > -     * Appends to the {@code builder} the deep comparison of
> > -     * two {@code byte} arrays.
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@link Object}s.
> >       *
> >       * <ol>
> > -     *  <li>Check if arrays are the same using {@code ==}</li>
> > -     *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(byte, byte)}</li>
> > +     * <li>Check if {@code lhs == rhs}</li>
> > +     * <li>Check if either {@code lhs} or {@code rhs} is {@code null},
> > +     *     a {@code null} object is less than a non-{@code null}
> object</li>
> > +     * <li>Check the object contents</li>
> >       * </ol>
> >       *
> > -     * @param lhs  left-hand array
> > -     * @param rhs  right-hand array
> > +     * <p>{@code lhs} must either be an array or implement {@link
> Comparable}.</p>
> > +     *
> > +     * @param lhs  left-hand object
> > +     * @param rhs  right-hand object
> >       * @return this
> > +     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > +     *  with {@code lhs}
> >       */
> > -    public CompareToBuilder append(final byte[] lhs, final byte[] rhs) {
> > +    public CompareToBuilder append(final Object lhs, final Object rhs) {
> > +        return append(lhs, rhs, null);
> > +    }
> > +
> > +    /**
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@link Object}s.
> > +     *
> > +     * <ol>
> > +     * <li>Check if {@code lhs == rhs}</li>
> > +     * <li>Check if either {@code lhs} or {@code rhs} is {@code null},
> > +     *     a {@code null} object is less than a non-{@code null}
> object</li>
> > +     * <li>Check the object contents</li>
> > +     * </ol>
> > +     *
> > +     * <p>If {@code lhs} is an array, array comparison methods will be
> used.
> > +     * Otherwise {@code comparator} will be used to compare the objects.
> > +     * If {@code comparator} is {@code null}, {@code lhs} must
> > +     * implement {@link Comparable} instead.</p>
> > +     *
> > +     * @param lhs  left-hand object
> > +     * @param rhs  right-hand object
> > +     * @param comparator  {@link Comparator} used to compare the
> objects,
> > +     *  {@code null} means treat lhs as {@link Comparable}
> > +     * @return this
> > +     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > +     *  with {@code lhs}
> > +     * @since 2.0
> > +     */
> > +    public CompareToBuilder append(final Object lhs, final Object rhs,
> final Comparator<?> comparator) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -865,72 +804,70 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >              comparison = 1;
> >              return this;
> >          }
> > -        if (lhs.length != rhs.length) {
> > -            comparison = lhs.length < rhs.length ? -1 : 1;
> > -            return this;
> > -        }
> > -        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > -            append(lhs[i], rhs[i]);
> > +        if (ObjectUtils.isArray(lhs)) {
> > +            // factor out array case in order to keep method small
> enough to be inlined
> > +            appendArray(lhs, rhs, comparator);
> > +        } else // the simple case, not an array, just test the element
> > +        if (comparator == null) {
> > +            @SuppressWarnings("unchecked") // assume this can be done;
> if not throw CCE as per Javadoc
> > +            final Comparable<Object> comparable = (Comparable<Object>)
> lhs;
> > +            comparison = comparable.compareTo(rhs);
> > +        } else {
> > +            @SuppressWarnings("unchecked") // assume this can be done;
> if not throw CCE as per Javadoc
> > +            final Comparator<Object> comparator2 = (Comparator<Object>)
> comparator;
> > +            comparison = comparator2.compare(lhs, rhs);
> >          }
> >          return this;
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code double} arrays.
> > +     * two {@link Object} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(double, double)}</li>
> > +     *  <li>Check array length, a short length array is less than a
> long length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(Object, Object, Comparator)}</li>
> >       * </ol>
> >       *
> > +     * <p>This method will also will be called for the top level of
> multi-dimensional,
> > +     * ragged, and multi-typed arrays.</p>
> > +     *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> >       * @return this
> > +     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > +     *  with {@code lhs}
> >       */
> > -    public CompareToBuilder append(final double[] lhs, final double[]
> rhs) {
> > -        if (comparison != 0) {
> > -            return this;
> > -        }
> > -        if (lhs == rhs) {
> > -            return this;
> > -        }
> > -        if (lhs == null) {
> > -            comparison = -1;
> > -            return this;
> > -        }
> > -        if (rhs == null) {
> > -            comparison = 1;
> > -            return this;
> > -        }
> > -        if (lhs.length != rhs.length) {
> > -            comparison = lhs.length < rhs.length ? -1 : 1;
> > -            return this;
> > -        }
> > -        for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > -            append(lhs[i], rhs[i]);
> > -        }
> > -        return this;
> > +    public CompareToBuilder append(final Object[] lhs, final Object[]
> rhs) {
> > +        return append(lhs, rhs, null);
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code float} arrays.
> > +     * two {@link Object} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> > -     *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(float, float)}</li>
> > +     *  <li>Check array length, a short length array is less than a
> long length array</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(Object, Object, Comparator)}</li>
> >       * </ol>
> >       *
> > +     * <p>This method will also will be called for the top level of
> multi-dimensional,
> > +     * ragged, and multi-typed arrays.</p>
> > +     *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> > +     * @param comparator  {@link Comparator} to use to compare the
> array elements,
> > +     *  {@code null} means to treat {@code lhs} elements as {@link
> Comparable}.
> >       * @return this
> > +     * @throws ClassCastException  if {@code rhs} is not
> assignment-compatible
> > +     *  with {@code lhs}
> > +     * @since 2.0
> >       */
> > -    public CompareToBuilder append(final float[] lhs, final float[]
> rhs) {
> > +    public CompareToBuilder append(final Object[] lhs, final Object[]
> rhs, final Comparator<?> comparator) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -950,27 +887,43 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >              return this;
> >          }
> >          for (int i = 0; i < lhs.length && comparison == 0; i++) {
> > -            append(lhs[i], rhs[i]);
> > +            append(lhs[i], rhs[i], comparator);
> > +        }
> > +        return this;
> > +    }
> > +
> > +    /**
> > +     * Appends to the {@code builder} the comparison of
> > +     * two {@code short}s.
> > +     *
> > +     * @param lhs  left-hand value
> > +     * @param rhs  right-hand value
> > +     * @return this
> > +     */
> > +    public CompareToBuilder append(final short lhs, final short rhs) {
> > +        if (comparison != 0) {
> > +            return this;
> >          }
> > +        comparison = Short.compare(lhs, rhs);
> >          return this;
> >      }
> >
> >      /**
> >       * Appends to the {@code builder} the deep comparison of
> > -     * two {@code boolean} arrays.
> > +     * two {@code short} arrays.
> >       *
> >       * <ol>
> >       *  <li>Check if arrays are the same using {@code ==}</li>
> >       *  <li>Check if for {@code null}, {@code null} is less than
> non-{@code null}</li>
> >       *  <li>Check array length, a shorter length array is less than a
> longer length array</li>
> > -     *  <li>Check array contents element by element using {@link
> #append(boolean, boolean)}</li>
> > +     *  <li>Check array contents element by element using {@link
> #append(short, short)}</li>
> >       * </ol>
> >       *
> >       * @param lhs  left-hand array
> >       * @param rhs  right-hand array
> >       * @return this
> >       */
> > -    public CompareToBuilder append(final boolean[] lhs, final boolean[]
> rhs) {
> > +    public CompareToBuilder append(final short[] lhs, final short[]
> rhs) {
> >          if (comparison != 0) {
> >              return this;
> >          }
> > @@ -995,17 +948,47 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >          return this;
> >      }
> >
> > +    private void appendArray(final Object lhs, final Object rhs, final
> Comparator<?> comparator) {
> > +        // switch on type of array, to dispatch to the correct handler
> > +        // handles multidimensional arrays
> > +        // throws a ClassCastException if rhs is not the correct array
> type
> > +        if (lhs instanceof long[]) {
> > +            append((long[]) lhs, (long[]) rhs);
> > +        } else if (lhs instanceof int[]) {
> > +            append((int[]) lhs, (int[]) rhs);
> > +        } else if (lhs instanceof short[]) {
> > +            append((short[]) lhs, (short[]) rhs);
> > +        } else if (lhs instanceof char[]) {
> > +            append((char[]) lhs, (char[]) rhs);
> > +        } else if (lhs instanceof byte[]) {
> > +            append((byte[]) lhs, (byte[]) rhs);
> > +        } else if (lhs instanceof double[]) {
> > +            append((double[]) lhs, (double[]) rhs);
> > +        } else if (lhs instanceof float[]) {
> > +            append((float[]) lhs, (float[]) rhs);
> > +        } else if (lhs instanceof boolean[]) {
> > +            append((boolean[]) lhs, (boolean[]) rhs);
> > +        } else {
> > +            // not an array of primitives
> > +            // throws a ClassCastException if rhs is not an array
> > +            append((Object[]) lhs, (Object[]) rhs, comparator);
> > +        }
> > +    }
> > +
> >      /**
> > -     * Returns a negative integer, a positive integer, or zero as
> > -     * the {@code builder} has judged the "left-hand" side
> > -     * as less than, greater than, or equal to the "right-hand"
> > -     * side.
> > +     * Appends to the {@code builder} the {@code compareTo(Object)}
> > +     * result of the superclass.
> >       *
> > -     * @return final comparison result
> > -     * @see #build()
> > +     * @param superCompareTo  result of calling {@code
> super.compareTo(Object)}
> > +     * @return this
> > +     * @since 2.0
> >       */
> > -    public int toComparison() {
> > -        return comparison;
> > +    public CompareToBuilder appendSuper(final int superCompareTo) {
> > +        if (comparison != 0) {
> > +            return this;
> > +        }
> > +        comparison = superCompareTo;
> > +        return this;
> >      }
> >
> >      /**
> > @@ -1022,5 +1005,18 @@ public class CompareToBuilder implements
> Builder<Integer> {
> >      public Integer build() {
> >          return Integer.valueOf(toComparison());
> >      }
> > +
> > +    /**
> > +     * Returns a negative integer, a positive integer, or zero as
> > +     * the {@code builder} has judged the "left-hand" side
> > +     * as less than, greater than, or equal to the "right-hand"
> > +     * side.
> > +     *
> > +     * @return final comparison result
> > +     * @see #build()
> > +     */
> > +    public int toComparison() {
> > +        return comparison;
> > +    }
> >  }
> >
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
> b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
> > index 6f843ca9e..b34e9d390 100644
> > --- a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
> > +++ b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
> > @@ -561,19 +561,13 @@ public class EqualsBuilder implements
> Builder<Boolean> {
> >              final Field[] fields = clazz.getDeclaredFields();
> >              AccessibleObject.setAccessible(fields, true);
> >              for (int i = 0; i < fields.length && isEquals; i++) {
> > -                final Field f = fields[i];
> > -                if (!ArrayUtils.contains(excludeFields, f.getName())
> > -                    && !f.getName().contains("$")
> > -                    && (testTransients ||
> !Modifier.isTransient(f.getModifiers()))
> > -                    && !Modifier.isStatic(f.getModifiers())
> > -                    && !f.isAnnotationPresent(EqualsExclude.class)) {
> > -                    try {
> > -                        append(f.get(lhs), f.get(rhs));
> > -                    } catch (final IllegalAccessException e) {
> > -                        //this can't happen. Would get a Security
> exception instead
> > -                        //throw a runtime exception in case the
> impossible happens.
> > -                        throw new InternalError("Unexpected
> IllegalAccessException");
> > -                    }
> > +                final Field field = fields[i];
> > +                if (!ArrayUtils.contains(excludeFields, field.getName())
> > +                    && !field.getName().contains("$")
> > +                    && (testTransients ||
> !Modifier.isTransient(field.getModifiers()))
> > +                    && !Modifier.isStatic(field.getModifiers())
> > +                    && !field.isAnnotationPresent(EqualsExclude.class))
> {
> > +                    append(Reflection.getUnchecked(field, lhs),
> Reflection.getUnchecked(field, rhs));
> >                  }
> >              }
> >          } finally {
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
> b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
> > index 9c86c76f7..afe59a8bd 100644
> > --- a/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
> > +++ b/src/main/java/org/apache/commons/lang3/builder/HashCodeBuilder.java
> > @@ -191,14 +191,7 @@ public class HashCodeBuilder implements
> Builder<Integer> {
> >                      && (useTransients ||
> !Modifier.isTransient(field.getModifiers()))
> >                      && !Modifier.isStatic(field.getModifiers())
> >                      &&
> !field.isAnnotationPresent(HashCodeExclude.class)) {
> > -                    try {
> > -                        final Object fieldValue = field.get(object);
> > -                        builder.append(fieldValue);
> > -                    } catch (final IllegalAccessException e) {
> > -                        // this can't happen. Would get a Security
> exception instead
> > -                        // throw a runtime exception in case the
> impossible happens.
> > -                        throw new InternalError("Unexpected
> IllegalAccessException");
> > -                    }
> > +                    builder.append(Reflection.getUnchecked(field,
> object));
> >                  }
> >              }
> >          } finally {
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/Reflection.java
> b/src/main/java/org/apache/commons/lang3/builder/Reflection.java
> > new file mode 100644
> > index 000000000..119bfe9b2
> > --- /dev/null
> > +++ b/src/main/java/org/apache/commons/lang3/builder/Reflection.java
> > @@ -0,0 +1,44 @@
> > +/*
> > + * Licensed to the Apache Software Foundation (ASF) under one or more
> > + * contributor license agreements.  See the NOTICE file distributed with
> > + * this work for additional information regarding copyright ownership.
> > + * The ASF licenses this file to You under the Apache License, Version
> 2.0
> > + * (the "License"); you may not use this file except in compliance with
> > + * the License.  You may obtain a copy of the License at
> > + *
> > + *      http://www.apache.org/licenses/LICENSE-2.0
> > + *
> > + * Unless required by applicable law or agreed to in writing, software
> > + * distributed under the License is distributed on an "AS IS" BASIS,
> > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > + * See the License for the specific language governing permissions and
> > + * limitations under the License.
> > + */
> > +
> > +package org.apache.commons.lang3.builder;
> > +
> > +import java.lang.reflect.Field;
> > +import java.util.Objects;
> > +
> > +/**
> > + * Package-private reflection code.
> > + */
> > +class Reflection {
> > +
> > +    /**
> > +     * Delegates to {@link Field#get(Object)} and rethrows {@link
> IllegalAccessException} as {@link IllegalArgumentException}.
> > +     *
> > +     * @param field The receiver of the get call.
> > +     * @param obj   The argument of the get call.
> > +     * @return The result of the get call.
> > +     * @throws IllegalArgumentException Thrown after catching {@link
> IllegalAccessException}.
> > +     */
> > +    static Object getUnchecked(final Field field, final Object obj) {
> > +        try {
> > +            return Objects.requireNonNull(field, "field").get(obj);
> > +        } catch (IllegalAccessException e) {
> > +            throw new IllegalArgumentException(e);
> > +        }
> > +    }
> > +
> > +}
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/ReflectionDiffBuilder.java
> b/src/main/java/org/apache/commons/lang3/builder/ReflectionDiffBuilder.java
> > index bacc0cb89..a5a8f9496 100644
> > ---
> a/src/main/java/org/apache/commons/lang3/builder/ReflectionDiffBuilder.java
> > +++
> b/src/main/java/org/apache/commons/lang3/builder/ReflectionDiffBuilder.java
> > @@ -151,12 +151,11 @@ public class ReflectionDiffBuilder<T> implements
> Builder<DiffResult<T>> {
> >          for (final Field field : FieldUtils.getAllFields(clazz)) {
> >              if (accept(field)) {
> >                  try {
> > -                    diffBuilder.append(field.getName(),
> FieldUtils.readField(field, left, true),
> > -                            FieldUtils.readField(field, right, true));
> > -                } catch (final IllegalAccessException ex) {
> > +                    diffBuilder.append(field.getName(),
> FieldUtils.readField(field, left, true), FieldUtils.readField(field, right,
> true));
> > +                } catch (final IllegalAccessException e) {
> >                      // this can't happen. Would get a Security
> exception instead
> >                      // throw a runtime exception in case the impossible
> happens.
> > -                    throw new InternalError("Unexpected
> IllegalAccessException: " + ex.getMessage());
> > +                    throw new IllegalArgumentException("Unexpected
> IllegalAccessException: " + e.getMessage(), e);
> >                  }
> >              }
> >          }
> > diff --git
> a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
> b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
> > index 8bb0d0e10..d6413681b 100644
> > ---
> a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
> > +++
> b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
> > @@ -657,16 +657,10 @@ public class ReflectionToStringBuilder extends
> ToStringBuilder {
> >          for (final Field field : fields) {
> >              final String fieldName = field.getName();
> >              if (this.accept(field)) {
> > -                try {
> > -                    // Warning: Field.get(Object) creates wrappers
> objects for primitive types.
> > -                    final Object fieldValue = this.getValue(field);
> > -                    if (!excludeNullValues || fieldValue != null) {
> > -                        this.append(fieldName, fieldValue,
> !field.isAnnotationPresent(ToStringSummary.class));
> > -                    }
> > -                } catch (final IllegalAccessException ex) {
> > -                    // this can't happen. Would get a Security
> exception instead
> > -                    // throw a runtime exception in case the impossible
> happens.
> > -                    throw new InternalError("Unexpected
> IllegalAccessException: " + ex.getMessage());
> > +                // Warning: Field.get(Object) creates wrappers objects
> for primitive types.
> > +                final Object fieldValue =
> Reflection.getUnchecked(field, getObject());
> > +                if (!excludeNullValues || fieldValue != null) {
> > +                    this.append(fieldName, fieldValue,
> !field.isAnnotationPresent(ToStringSummary.class));
> >                  }
> >              }
> >          }
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
>
>

Reply via email to