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