From b2ad5e80bbed74153dd45a871041d04294c2bdb9 Mon Sep 17 00:00:00 2001 From: Matthew Jason Benson Date: Fri, 11 Oct 2013 19:38:49 +0000 Subject: [PATCH] a bit of dog food and a lot of javadoc tweakage git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1531403 13f79535-47bb-0310-9956-ffa450edef68 --- .../lang3/reflect/ConstructorUtils.java | 96 ++--- .../commons/lang3/reflect/FieldUtils.java | 392 +++++++++--------- .../commons/lang3/reflect/MemberUtils.java | 20 +- .../commons/lang3/reflect/MethodUtils.java | 157 +++---- 4 files changed, 316 insertions(+), 349 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/reflect/ConstructorUtils.java b/src/main/java/org/apache/commons/lang3/reflect/ConstructorUtils.java index 4484f1be3..f980945a2 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/ConstructorUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/ConstructorUtils.java @@ -16,26 +16,28 @@ */ package org.apache.commons.lang3.reflect; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ClassUtils; +import org.apache.commons.lang3.Validate; /** *

Utility reflection methods focused on constructors, modeled after * {@link MethodUtils}.

* *

Known Limitations

Accessing Public Constructors In A Default - * Access Superclass

There is an issue when invoking public constructors - * contained in a default access superclass. Reflection locates these - * constructors fine and correctly assigns them as public. However, an - * IllegalAccessException is thrown if the constructors is + * Access Superclass

There is an issue when invoking {@code public} constructors + * contained in a default access superclass. Reflection correctly locates these + * constructors and assigns them as {@code public}. However, an + * {@link IllegalAccessException} is thrown if the constructor is * invoked.

* - *

ConstructorUtils contains a workaround for this situation. It - * will attempt to call setAccessible on this constructor. If this + *

{@link ConstructorUtils} contains a workaround for this situation: it + * will attempt to call {@link AccessibleObject#setAccessible(boolean)} on this constructor. If this * call succeeds, then the method can be invoked as normal. This call will only * succeed when the application has sufficient security privileges. If this call * fails then a warning will be logged and the method may fail.

@@ -48,9 +50,9 @@ public class ConstructorUtils { /** *

ConstructorUtils instances should NOT be constructed in standard * programming. Instead, the class should be used as - * ConstructorUtils.invokeConstructor(cls, args).

+ * {@code ConstructorUtils.invokeConstructor(cls, args)}.

* - *

This constructor is public to permit tools that require a JavaBean + *

This constructor is {@code public} to permit tools that require a JavaBean * instance to operate.

*/ public ConstructorUtils() { @@ -65,10 +67,11 @@ public class ConstructorUtils { * The constructor signature must match the argument types by assignment compatibility.

* * @param the type to be constructed - * @param cls the class to be constructed, not null - * @param args the array of arguments, null treated as empty - * @return new instance of cls, not null + * @param cls the class to be constructed, not {@code null} + * @param args the array of arguments, {@code null treated as empty + * @return new instance of {@code cls}, not {@code null} * + * @throws NullPointerException if {@code cls} is {@code null} * @throws NoSuchMethodException if a matching constructor cannot be found * @throws IllegalAccessException if invocation is not permitted by security * @throws InvocationTargetException if an error occurs on invocation @@ -78,9 +81,7 @@ public class ConstructorUtils { public static T invokeConstructor(final Class cls, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class parameterTypes[] = ClassUtils.toClass(args); return invokeConstructor(cls, args, parameterTypes); } @@ -93,11 +94,12 @@ public class ConstructorUtils { * The constructor signature must match the parameter types by assignment compatibility.

* * @param the type to be constructed - * @param cls the class to be constructed, not null - * @param args the array of arguments, null treated as empty - * @param parameterTypes the array of parameter types, null treated as empty - * @return new instance of cls, not null + * @param cls the class to be constructed, not {@code null} + * @param args the array of arguments, {@code null} treated as empty + * @param parameterTypes the array of parameter types, {@code null} treated as empty + * @return new instance of {@code cls}, not {@code null} * + * @throws NullPointerException if {@code cls} is {@code null} * @throws NoSuchMethodException if a matching constructor cannot be found * @throws IllegalAccessException if invocation is not permitted by security * @throws InvocationTargetException if an error occurs on invocation @@ -107,12 +109,8 @@ public class ConstructorUtils { public static T invokeConstructor(final Class cls, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); final Constructor ctor = getMatchingAccessibleConstructor(cls, parameterTypes); if (ctor == null) { throw new NoSuchMethodException( @@ -129,10 +127,11 @@ public class ConstructorUtils { * The constructor signature must match the argument types exactly.

* * @param the type to be constructed - * @param cls the class to be constructed, not null - * @param args the array of arguments, null treated as empty - * @return new instance of cls, not null + * @param cls the class to be constructed, not {@code null} + * @param args the array of arguments, {@code null treated as empty + * @return new instance of {@code cls}, not {@code null * + * @throws NullPointerException if {@code cls} is {@code null} * @throws NoSuchMethodException if a matching constructor cannot be found * @throws IllegalAccessException if invocation is not permitted by security * @throws InvocationTargetException if an error occurs on invocation @@ -142,9 +141,7 @@ public class ConstructorUtils { public static T invokeExactConstructor(final Class cls, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class parameterTypes[] = ClassUtils.toClass(args); return invokeExactConstructor(cls, args, parameterTypes); } @@ -157,11 +154,12 @@ public class ConstructorUtils { * The constructor signature must match the parameter types exactly.

* * @param the type to be constructed - * @param cls the class to be constructed, not null - * @param args the array of arguments, null treated as empty - * @param parameterTypes the array of parameter types, null treated as empty - * @return new instance of cls, not null + * @param cls the class to be constructed, not {@code null} + * @param args the array of arguments, {@code null} treated as empty + * @param parameterTypes the array of parameter types, {@code null} treated as empty + * @return new instance of cls, not {@code null} * + * @throws NullPointerException if {@code cls} is {@code null} * @throws NoSuchMethodException if a matching constructor cannot be found * @throws IllegalAccessException if invocation is not permitted by security * @throws InvocationTargetException if an error occurs on invocation @@ -171,12 +169,8 @@ public class ConstructorUtils { public static T invokeExactConstructor(final Class cls, Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); final Constructor ctor = getAccessibleConstructor(cls, parameterTypes); if (ctor == null) { throw new NoSuchMethodException( @@ -193,14 +187,16 @@ public class ConstructorUtils { * The constructor signature must match the parameter types exactly.

* * @param the constructor type - * @param cls the class to find a constructor for, not null - * @param parameterTypes the array of parameter types, null treated as empty - * @return the constructor, null if no matching accessible constructor found + * @param cls the class to find a constructor for, not {@code null} + * @param parameterTypes the array of parameter types, {@code null} treated as empty + * @return the constructor, {@code null} if no matching accessible constructor found * @see Class#getConstructor * @see #getAccessibleConstructor(java.lang.reflect.Constructor) + * @throws NullPointerException if {@code cls} is {@code null} */ public static Constructor getAccessibleConstructor(final Class cls, final Class... parameterTypes) { + Validate.notNull(cls, "class cannot be null"); try { return getAccessibleConstructor(cls.getConstructor(parameterTypes)); } catch (final NoSuchMethodException e) { @@ -214,11 +210,13 @@ public class ConstructorUtils { *

This simply ensures that the constructor is accessible.

* * @param the constructor type - * @param ctor the prototype constructor object, not null - * @return the constructor, null if no matching accessible constructor found + * @param ctor the prototype constructor object, not {@code null} + * @return the constructor, {@code null} if no matching accessible constructor found * @see java.lang.SecurityManager + * @throws NullPointerException if {@code ctor} is {@code null} */ public static Constructor getAccessibleConstructor(final Constructor ctor) { + Validate.notNull(ctor, "constructor cannot be null"); return MemberUtils.isAccessible(ctor) && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null; } @@ -232,16 +230,18 @@ public class ConstructorUtils { * *

First it checks if there is a constructor matching the exact signature. * If not then all the constructors of the class are checked to see if their - * signatures are assignment compatible with the parameter types. - * The first assignment compatible matching constructor is returned.

+ * signatures are assignment-compatible with the parameter types. + * The first assignment-compatible matching constructor is returned.

* * @param the constructor type - * @param cls the class to find a constructor for, not null + * @param cls the class to find a constructor for, not {@code null} * @param parameterTypes find method with compatible parameters * @return the constructor, null if no matching accessible constructor found + * @throws NullPointerException if {@code cls} is {@code null} */ public static Constructor getMatchingAccessibleConstructor(final Class cls, final Class... parameterTypes) { + Validate.notNull(cls, "class cannot be null"); // see if we can find the constructor directly // most of the time this works and it's much faster try { diff --git a/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java b/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java index f869cc964..860ad08fd 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/FieldUtils.java @@ -16,15 +16,18 @@ */ package org.apache.commons.lang3.reflect; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.ClassUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; /** - * Utilities for working with fields by reflection. Adapted and refactored from the dormant [reflect] Commons sandbox + * Utilities for working with {@link Field}s by reflection. Adapted and refactored from the dormant [reflect] Commons sandbox * component. *

* The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be @@ -36,24 +39,24 @@ import org.apache.commons.lang3.ClassUtils; public class FieldUtils { /** - * FieldUtils instances should NOT be constructed in standard programming. + * {@link FieldUtils} instances should NOT be constructed in standard programming. *

- * This constructor is public to permit tools that require a JavaBean instance to operate. + * This constructor is {@code public} to permit tools that require a JavaBean instance to operate.

*/ public FieldUtils() { super(); } /** - * Gets an accessible Field by name respecting scope. Superclasses/interfaces will be considered. + * Gets an accessible {@link Field} by name respecting scope. Superclasses/interfaces will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the Field object * @throws IllegalArgumentException - * if the class or field name is null + * if the class is {@code null}, or the field name is blank or empty */ public static Field getField(final Class cls, final String fieldName) { final Field field = getField(cls, fieldName, false); @@ -62,27 +65,24 @@ public class FieldUtils { } /** - * Gets an accessible Field by name breaking scope if requested. Superclasses/interfaces will be + * Gets an accessible {@link Field} by name, breaking scope if requested. Superclasses/interfaces will be * considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @return the Field object * @throws IllegalArgumentException - * if the class or field name is null + * if the class is {@code null}, or the field name is blank or empty or is matched at + * multiple places in the inheritance hierarchy */ public static Field getField(final Class cls, final String fieldName, final boolean forceAccess) { - if (cls == null) { - throw new IllegalArgumentException("The class must not be null"); - } - if (fieldName == null) { - throw new IllegalArgumentException("The field name must not be null"); - } + Validate.isTrue(cls != null, "The class must not be null"); + Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); // Sun Java 1.3 has a bugged implementation of getField hence we write the // code ourselves @@ -120,11 +120,9 @@ public class FieldUtils { Field match = null; for (final Class class1 : ClassUtils.getAllInterfaces(cls)) { try { - final Field test = ((Class) class1).getField(fieldName); - if (match != null) { - throw new IllegalArgumentException("Reference to field " + fieldName + " is ambiguous relative to " + cls + - "; a matching field exists on two or more implemented interfaces."); - } + final Field test = class1.getField(fieldName); + Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s" + + "; a matching field exists on two or more implemented interfaces.", fieldName, cls); match = test; } catch (final NoSuchFieldException ex) { // NOPMD // ignore @@ -134,42 +132,38 @@ public class FieldUtils { } /** - * Gets an accessible Field by name respecting scope. Only the specified class will be considered. + * Gets an accessible {@link Field} by name respecting scope. Only the specified class will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the Field object * @throws IllegalArgumentException - * if the class or field name is null + * if the class is {@code null}, or the field name is blank or empty */ public static Field getDeclaredField(final Class cls, final String fieldName) { return getDeclaredField(cls, fieldName, false); } /** - * Gets an accessible Field by name breaking scope if requested. Only the specified class will be + * Gets an accessible {@link Field} by name, breaking scope if requested. Only the specified class will be * considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False will only - * match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @return the Field object * @throws IllegalArgumentException - * if the class or field name is null + * if the class is {@code null}, or the field name is blank or empty */ public static Field getDeclaredField(final Class cls, final String fieldName, final boolean forceAccess) { - if (cls == null) { - throw new IllegalArgumentException("The class must not be null"); - } - if (fieldName == null) { - throw new IllegalArgumentException("The field name must not be null"); - } + Validate.isTrue(cls != null, "The class must not be null"); + Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty"); try { // only consider the specified class by using getDeclaredField() final Field field = cls.getDeclaredField(fieldName); @@ -191,8 +185,10 @@ public class FieldUtils { * Gets all fields of the given class and its parents (if any). * * @param cls - * the class to query - * @return an array of Fields (maybe an empty array). + * the {@link Class} to query + * @return an array of Fields (possibly empty). + * @throws IllegalArgumentException + * if the class is {@code null} * @since 3.2 */ public static Field[] getAllFields(Class cls) { @@ -204,15 +200,15 @@ public class FieldUtils { * Gets all fields of the given class and its parents (if any). * * @param cls - * the class to query - * @return an array of Fields (maybe an empty array). + * the {@link Class} to query + * @return an array of Fields (possibly empty). + * @throws IllegalArgumentException + * if the class is {@code null} * @since 3.2 */ public static List getAllFieldsList(Class cls) { - if (cls == null) { - throw new IllegalArgumentException("The class must not be null"); - } - List allFields = new ArrayList(); + Validate.isTrue(cls != null, "The class must not be null"); + final List allFields = new ArrayList(); Class currentClass = cls; while (currentClass != null) { final Field[] declaredFields = currentClass.getDeclaredFields(); @@ -225,13 +221,13 @@ public class FieldUtils { } /** - * Reads an accessible static Field. + * Reads an accessible {@code static} {@link Field}. * * @param field * to read * @return the field value * @throws IllegalArgumentException - * if the field is null or not static + * if the field is {@code null}, or not {@code static} * @throws IllegalAccessException * if the field is not accessible */ @@ -240,38 +236,35 @@ public class FieldUtils { } /** - * Reads a static Field. + * Reads a static {@link Field}. * * @param field * to read * @param forceAccess - * whether to break scope restrictions using the setAccessible method. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. * @return the field value * @throws IllegalArgumentException - * if the field is null or not static + * if the field is {@code null} or not {@code static} * @throws IllegalAccessException * if the field is not made accessible */ public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException { - if (field == null) { - throw new IllegalArgumentException("The field must not be null"); - } - if (!Modifier.isStatic(field.getModifiers())) { - throw new IllegalArgumentException("The field '" + field.getName() + "' is not static"); - } + Validate.isTrue(field != null, "The field must not be null"); + Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field '%s' is not static", field.getName()); return readField(field, (Object) null, forceAccess); } /** - * Reads the named public static field. Superclasses will be considered. + * Reads the named {@code public static} {@link Field}. Superclasses will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the value of the field * @throws IllegalArgumentException - * if the class is null, the field name is null or if the field could not be found + * if the class is {@code null}, or the field name is blank or empty, + * is not {@code static}, or could not be found * @throws IllegalAccessException * if the field is not accessible */ @@ -280,40 +273,41 @@ public class FieldUtils { } /** - * Reads the named static field. Superclasses will be considered. + * Reads the named {@code static} {@link Field}. Superclasses will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(false)} method. + * {@code false} will only match {@code public} fields. * @return the Field object * @throws IllegalArgumentException - * if the class is null, the field name is null or if the field could not be found + * if the class is {@code null}, or the field name is blank or empty, + * is not {@code static}, or could not be found * @throws IllegalAccessException * if the field is not made accessible */ public static Object readStaticField(final Class cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { final Field field = getField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls); - } + Validate.isTrue(field != null, "Cannot locate field '%s' on %s", fieldName, cls); // already forced access above, don't repeat it here: return readStaticField(field, false); } /** - * Gets a static Field value by name. The field must be public. Only the specified class will be considered. + * Gets the value of a {@code static} {@link Field} by name. The field must be {@code public}. + * Only the specified class will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the value of the field * @throws IllegalArgumentException - * if the class is null, the field name is null or if the field could not be found + * if the class is {@code null}, or the field name is blank or empty, + * is not {@code static}, or could not be found * @throws IllegalAccessException * if the field is not accessible */ @@ -322,40 +316,40 @@ public class FieldUtils { } /** - * Gets a static Field value by name. Only the specified class will be considered. + * Gets the value of a {@code static} {@link Field} by name. + * Only the specified class will be considered. * * @param cls - * the class to reflect, must not be null + * the {@link Class} to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @return the Field object * @throws IllegalArgumentException - * if the class is null, the field name is null or if the field could not be found + * if the class is {@code null}, or the field name is blank or empty, + * is not {@code static}, or could not be found * @throws IllegalAccessException * if the field is not made accessible */ public static Object readDeclaredStaticField(final Class cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { final Field field = getDeclaredField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName); - } + Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); // already forced access above, don't repeat it here: return readStaticField(field, false); } /** - * Reads an accessible Field. + * Reads an accessible {@link Field}. * * @param field * the field to use * @param target - * the object to call on, may be null for static fields + * the object to call on, may be {@code null} for {@code static} fields * @return the field value * @throws IllegalArgumentException - * if the field is null + * if the field is {@code null} * @throws IllegalAccessException * if the field is not accessible */ @@ -364,24 +358,22 @@ public class FieldUtils { } /** - * Reads a Field. + * Reads a {@link Field}. * * @param field * the field to use * @param target - * the object to call on, may be null for static fields + * the object to call on, may be {@code null} for {@code static} fields * @param forceAccess - * whether to break scope restrictions using the setAccessible method. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. * @return the field value * @throws IllegalArgumentException - * if the field is null + * if the field is {@code null} * @throws IllegalAccessException * if the field is not made accessible */ public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException { - if (field == null) { - throw new IllegalArgumentException("The field must not be null"); - } + Validate.isTrue(field != null, "The field must not be null"); if (forceAccess && !field.isAccessible()) { field.setAccessible(true); } else { @@ -391,268 +383,270 @@ public class FieldUtils { } /** - * Reads the named public field. Superclasses will be considered. + * Reads the named {@code public} {@link Field}. Superclasses will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the value of the field * @throws IllegalArgumentException - * if the class or field name is null + * if the class is {@code null}, or + * the field name is blank or empty or could not be found * @throws IllegalAccessException - * if the named field is not public + * if the named field is not {@code public} */ public static Object readField(final Object target, final String fieldName) throws IllegalAccessException { return readField(target, fieldName, false); } /** - * Reads the named field. Superclasses will be considered. + * Reads the named {@link Field}. Superclasses will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @return the field value * @throws IllegalArgumentException - * if the class or field name is null + * if {@code target} is {@code null}, or + * the field name is blank or empty or could not be found * @throws IllegalAccessException * if the named field is not made accessible */ public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { - if (target == null) { - throw new IllegalArgumentException("target object must not be null"); - } + Validate.isTrue(target != null, "target object must not be null"); final Class cls = target.getClass(); final Field field = getField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls); - } + Validate.isTrue(field != null, "Cannot locate field %s on %s" , fieldName, cls); // already forced access above, don't repeat it here: return readField(field, target); } /** - * Reads the named public field. Only the class of the specified object will be considered. + * Reads the named {@code public} {@link Field}. Only the class of the specified object will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @return the value of the field * @throws IllegalArgumentException - * if the class or field name is null + * if {@code target} is {@code null}, or + * the field name is blank or empty or could not be found * @throws IllegalAccessException - * if the named field is not public + * if the named field is not {@code public} */ public static Object readDeclaredField(final Object target, final String fieldName) throws IllegalAccessException { return readDeclaredField(target, fieldName, false); } /** - * Gets a Field value by name. Only the class of the specified object will be considered. + * Gets a {@link Field} value by name. Only the class of the specified object will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match public fields. * @return the Field object * @throws IllegalArgumentException - * if target or fieldName is null + * if {@code target} is {@code null}, or + * the field name is blank or empty or could not be found * @throws IllegalAccessException * if the field is not made accessible */ public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { - if (target == null) { - throw new IllegalArgumentException("target object must not be null"); - } + Validate.isTrue(target != null, "target object must not be null"); final Class cls = target.getClass(); final Field field = getDeclaredField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName); - } + Validate.isTrue(field != null, "Cannot locate declared field %s.%s" , cls, fieldName); // already forced access above, don't repeat it here: return readField(field, target); } /** - * Writes a public static Field. + * Writes a {@code public static} {@link Field}. * * @param field * to write * @param value * to set * @throws IllegalArgumentException - * if the field is null or not static + * if the field is {@code null} or not {@code static}, + * or {@code value} is not assignable * @throws IllegalAccessException - * if the field is not public or is final + * if the field is not {@code public} or is {@code final} */ public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException { writeStaticField(field, value, false); } /** - * Writes a static Field. + * Writes a static {@link Field}. * * @param field * to write * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. {@code false} + * will only match {@code public} fields. * @throws IllegalArgumentException - * if the field is null or not static + * if the field is {@code null} or not {@code static}, + * or {@code value} is not assignable * @throws IllegalAccessException - * if the field is not made accessible or is final + * if the field is not made accessible or is {@code final} */ public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException { - if (field == null) { - throw new IllegalArgumentException("The field must not be null"); - } - if (!Modifier.isStatic(field.getModifiers())) { - throw new IllegalArgumentException("The field '" + field.getName() + "' is not static"); - } + Validate.isTrue(field != null, "The field must not be null"); + Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field %s.%s is not static", + field.getDeclaringClass().getName(), field.getName()); writeField(field, (Object) null, value, forceAccess); } /** - * Writes a named public static Field. Superclasses will be considered. + * Writes a named {@code public static} {@link Field}. Superclasses will be considered. * * @param cls - * Class on which the Field is to be found + * {@link Class} on which the field is to be found * @param fieldName * to write * @param value * to set * @throws IllegalArgumentException - * if the field cannot be located or is not static + * if {@code cls} is {@code null}, + * the field name is blank or empty, + * the field cannot be located or is not {@code static}, or + * {@code value} is not assignable * @throws IllegalAccessException - * if the field is not public or is final + * if the field is not {@code public} or is {@code final} */ public static void writeStaticField(final Class cls, final String fieldName, final Object value) throws IllegalAccessException { writeStaticField(cls, fieldName, value, false); } /** - * Writes a named static Field. Superclasses will be considered. + * Writes a named {@code static} {@link Field}. Superclasses will be considered. * * @param cls - * Class on which the Field is to be found + * {@link Class} on which the field is to be found * @param fieldName * to write * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @throws IllegalArgumentException - * if the field cannot be located or is not static + * if {@code cls} is {@code null}, + * the field name is blank or empty, + * the field cannot be located or is not {@code static}, or + * {@code value} is not assignable * @throws IllegalAccessException - * if the field is not made accessible or is final + * if the field is not made accessible or is {@code final} */ public static void writeStaticField(final Class cls, final String fieldName, final Object value, final boolean forceAccess) throws IllegalAccessException { final Field field = getField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls); - } + Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls); // already forced access above, don't repeat it here: writeStaticField(field, value); } /** - * Writes a named public static Field. Only the specified class will be considered. + * Writes a named {@code public static} {@link Field}. Only the specified class will be considered. * * @param cls - * Class on which the Field is to be found + * {@link Class} on which the field is to be found * @param fieldName * to write * @param value * to set * @throws IllegalArgumentException - * if the field cannot be located or is not static + * if {@code cls} is {@code null}, + * the field name is blank or empty, + * the field cannot be located or is not {@code static}, or + * {@code value} is not assignable * @throws IllegalAccessException - * if the field is not public or is final + * if the field is not {@code public} or is {@code final} */ public static void writeDeclaredStaticField(final Class cls, final String fieldName, final Object value) throws IllegalAccessException { writeDeclaredStaticField(cls, fieldName, value, false); } /** - * Writes a named static Field. Only the specified class will be considered. + * Writes a named {@code static} {@link Field}. Only the specified class will be considered. * * @param cls - * Class on which the Field is to be found + * {@link Class} on which the field is to be found * @param fieldName * to write * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @throws IllegalArgumentException - * if the field cannot be located or is not static + * if {@code cls} is {@code null}, + * the field name is blank or empty, + * the field cannot be located or is not {@code static}, or + * {@code value} is not assignable * @throws IllegalAccessException - * if the field is not made accessible or is final + * if the field is not made accessible or is {@code final} */ public static void writeDeclaredStaticField(final Class cls, final String fieldName, final Object value, final boolean forceAccess) throws IllegalAccessException { final Field field = getDeclaredField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName); - } + Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); // already forced access above, don't repeat it here: writeField(field, (Object) null, value); } /** - * Writes an accessible field. + * Writes an accessible {@link Field}. * * @param field * to write * @param target - * the object to call on, may be null for static fields + * the object to call on, may be {@code null} for {@code static} fields * @param value * to set - * @throws IllegalArgumentException - * if the field is null * @throws IllegalAccessException - * if the field is not accessible or is final + * if the field or target is {@code null}, + * the field is not accessible or is {@code final}, or + * {@code value} is not assignable */ public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException { writeField(field, target, value, false); } /** - * Writes a field. + * Writes a {@link Field}. * * @param field * to write * @param target - * the object to call on, may be null for static fields + * the object to call on, may be {@code null} for {@code static} fields * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @throws IllegalArgumentException - * if the field is null + * if the field is {@code null} or + * {@code value} is not assignable * @throws IllegalAccessException - * if the field is not made accessible or is final + * if the field is not made accessible or is {@code final} */ public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess) throws IllegalAccessException { - if (field == null) { - throw new IllegalArgumentException("The field must not be null"); - } + Validate.isTrue(field != null, "The field must not be null"); if (forceAccess && !field.isAccessible()) { field.setAccessible(true); } else { @@ -662,16 +656,18 @@ public class FieldUtils { } /** - * Writes a public field. Superclasses will be considered. + * Writes a {@code public} {@link Field}. Superclasses will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param value * to set * @throws IllegalArgumentException - * if target or fieldName is null + * if {@code target} is {@code null}, + * {@code fieldName} is blank or empty or could not be found, + * or {@code value} is not assignable * @throws IllegalAccessException * if the field is not accessible */ @@ -680,47 +676,47 @@ public class FieldUtils { } /** - * Writes a field. Superclasses will be considered. + * Writes a {@link Field}. Superclasses will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. {@code false} + * will only match {@code public} fields. * @throws IllegalArgumentException - * if target or fieldName is null + * if {@code target} is {@code null}, + * {@code fieldName} is blank or empty or could not be found, + * or {@code value} is not assignable * @throws IllegalAccessException * if the field is not made accessible */ public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess) throws IllegalAccessException { - if (target == null) { - throw new IllegalArgumentException("target object must not be null"); - } + Validate.isTrue(target != null, "target object must not be null"); final Class cls = target.getClass(); final Field field = getField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName); - } + Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); // already forced access above, don't repeat it here: writeField(field, target, value); } /** - * Writes a public field. Only the specified class will be considered. + * Writes a {@code public} {@link Field}. Only the specified class will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param value * to set * @throws IllegalArgumentException - * if target or fieldName is null + * if {@code target} is {@code null}, + * {@code fieldName} is blank or empty or could not be found, + * or {@code value} is not assignable * @throws IllegalAccessException * if the field is not made accessible */ @@ -729,32 +725,30 @@ public class FieldUtils { } /** - * Writes a public field. Only the specified class will be considered. + * Writes a {@code public} {@link Field}. Only the specified class will be considered. * * @param target - * the object to reflect, must not be null + * the object to reflect, must not be {@code null} * @param fieldName * the field name to obtain * @param value * to set * @param forceAccess - * whether to break scope restrictions using the setAccessible method. False - * will only match public fields. + * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. + * {@code false} will only match {@code public} fields. * @throws IllegalArgumentException - * if target or fieldName is null + * if {@code target} is {@code null}, + * {@code fieldName} is blank or empty or could not be found, + * or {@code value} is not assignable * @throws IllegalAccessException * if the field is not made accessible */ public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess) throws IllegalAccessException { - if (target == null) { - throw new IllegalArgumentException("target object must not be null"); - } + Validate.isTrue(target != null, "target object must not be null"); final Class cls = target.getClass(); final Field field = getDeclaredField(cls, fieldName, forceAccess); - if (field == null) { - throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName); - } + Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName); // already forced access above, don't repeat it here: writeField(field, target, value); } diff --git a/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java b/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java index 006fcb710..aa5f0411a 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/MemberUtils.java @@ -23,8 +23,8 @@ import java.lang.reflect.Modifier; import org.apache.commons.lang3.ClassUtils; /** - * Contains common code for working with Methods/Constructors, extracted and - * refactored from MethodUtils when it was imported from Commons + * Contains common code for working with {@link Method}s/{@link Constructor}s, extracted and + * refactored from {@link MethodUtils} when it was imported from Commons * BeanUtils. * * @since 2.5 @@ -42,11 +42,11 @@ abstract class MemberUtils { /** * XXX Default access superclass workaround * - * When a public class has a default access superclass with public members, + * When a {@code public} class has a default access superclass with {@code public} members, * these members are accessible. Calling them from compiled code works fine. * Unfortunately, on some JVMs, using reflection to invoke these members - * seems to (wrongly) prevent access even when the modifier is public. - * Calling setAccessible(true) solves the problem but will only work from + * seems to (wrongly) prevent access even when the modifier is {@code public}. + * Calling {@code setAccessible(true)} solves the problem but will only work from * sufficiently privileged code. Better workarounds would be gratefully * accepted. * @param o the AccessibleObject to set as accessible @@ -69,16 +69,16 @@ abstract class MemberUtils { /** * Returns whether a given set of modifiers implies package access. * @param modifiers to test - * @return true unless package/protected/private modifier detected + * @return {@code true} unless {@code package}/{@code protected}/{@code private} modifier detected */ static boolean isPackageAccess(final int modifiers) { return (modifiers & ACCESS_TEST) == 0; } /** - * Returns whether a Member is accessible. + * Returns whether a {@link Member} is accessible. * @param m Member to check - * @return true if m is accessible + * @return {@code true} if m is accessible */ static boolean isAccessible(final Member m) { return m != null && Modifier.isPublic(m.getModifiers()) && !m.isSynthetic(); @@ -93,8 +93,8 @@ abstract class MemberUtils { * @param left the "left" parameter set * @param right the "right" parameter set * @param actual the runtime parameter types to match against - * left/right - * @return int consistent with compare semantics + * {@code left}/{@code right} + * @return int consistent with {@code compare} semantics */ static int compareParameterTypes(final Class[] left, final Class[] right, final Class[] actual) { final float leftCost = getTotalTransformationCost(actual, left); diff --git a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java index 3bad3f0f5..5ac5ee790 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java @@ -16,6 +16,7 @@ */ package org.apache.commons.lang3.reflect; +import java.lang.reflect.AccessibleObject; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -33,19 +34,19 @@ import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.ClassUtils.Interfaces; /** - *

Utility reflection methods focused on methods, originally from Commons BeanUtils. + *

Utility reflection methods focused on {@link Method}s, originally from Commons BeanUtils. * Differences from the BeanUtils version may be noted, especially where similar functionality * already existed within Lang. *

* *

Known Limitations

*

Accessing Public Methods In A Default Access Superclass

- *

There is an issue when invoking public methods contained in a default access superclass on JREs prior to 1.4. - * Reflection locates these methods fine and correctly assigns them as public. - * However, an IllegalAccessException is thrown if the method is invoked.

+ *

There is an issue when invoking {@code public} methods contained in a default access superclass on JREs prior to 1.4. + * Reflection locates these methods fine and correctly assigns them as {@code public}. + * However, an {@link IllegalAccessException} is thrown if the method is invoked.

* - *

MethodUtils contains a workaround for this situation. - * It will attempt to call setAccessible on this method. + *

{@link MethodUtils} contains a workaround for this situation. + * It will attempt to call {@link AccessibleObject#setAccessible(boolean)} on this method. * If this call succeeds, then the method can be invoked as normal. * This call will only succeed when the application has sufficient security privileges. * If this call fails then the method may fail.

@@ -56,11 +57,11 @@ import org.apache.commons.lang3.ClassUtils.Interfaces; public class MethodUtils { /** - *

MethodUtils instances should NOT be constructed in standard programming. + *

{@link MethodUtils} instances should NOT be constructed in standard programming. * Instead, the class should be used as - * MethodUtils.getAccessibleMethod(method).

+ * {@code MethodUtils.getAccessibleMethod(method)}.

* - *

This constructor is public to permit tools that require a JavaBean + *

This constructor is {@code public} to permit tools that require a JavaBean * instance to operate.

*/ public MethodUtils() { @@ -73,8 +74,8 @@ public class MethodUtils { *

This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.

* *

This method supports calls to methods taking primitive parameters - * via passing in wrapping classes. So, for example, a Boolean object - * would match a boolean primitive.

+ * via passing in wrapping classes. So, for example, a {@code Boolean} object + * would match a {@code boolean} primitive.

* *

This is a convenient wrapper for * {@link #invokeMethod(Object object,String methodName, Object[] args, Class[] parameterTypes)}. @@ -92,9 +93,7 @@ public class MethodUtils { public static Object invokeMethod(final Object object, final String methodName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class[] parameterTypes = ClassUtils.toClass(args); return invokeMethod(object, methodName, args, parameterTypes); } @@ -105,8 +104,8 @@ public class MethodUtils { *

This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.

* *

This method supports calls to methods taking primitive parameters - * via passing in wrapping classes. So, for example, a Boolean object - * would match a boolean primitive.

+ * via passing in wrapping classes. So, for example, a {@code Boolean} object + * would match a {@code boolean} primitive.

* * @param object invoke method on this object * @param methodName get method with this name @@ -122,12 +121,8 @@ public class MethodUtils { Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); + args = ArrayUtils.nullToEmpty(args); final Method method = getMatchingAccessibleMethod(object.getClass(), methodName, parameterTypes); if (method == null) { @@ -143,11 +138,11 @@ public class MethodUtils { * types.

* *

This uses reflection to invoke the method obtained from a call to - * getAccessibleMethod().

+ * {@link #getAccessibleMethod}(Class,String,Class[])}.

* * @param object invoke method on this object * @param methodName get method with this name - * @param args use these arguments - treat null as empty array + * @param args use these arguments - treat {@code null} as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -159,9 +154,7 @@ public class MethodUtils { public static Object invokeExactMethod(final Object object, final String methodName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class[] parameterTypes = ClassUtils.toClass(args); return invokeExactMethod(object, methodName, args, parameterTypes); } @@ -171,12 +164,12 @@ public class MethodUtils { * types given.

* *

This uses reflection to invoke the method obtained from a call to - * getAccessibleMethod().

+ * {@link #getAccessibleMethod(Class,String,Class[])}.

* * @param object invoke method on this object * @param methodName get method with this name * @param args use these arguments - treat null as empty array - * @param parameterTypes match these parameters - treat null as empty array + * @param parameterTypes match these parameters - treat {@code null} as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -189,12 +182,8 @@ public class MethodUtils { Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); final Method method = getAccessibleMethod(object.getClass(), methodName, parameterTypes); if (method == null) { @@ -206,7 +195,7 @@ public class MethodUtils { } /** - *

Invokes a static method whose parameter types match exactly the parameter + *

Invokes a {@code static} method whose parameter types match exactly the parameter * types given.

* *

This uses reflection to invoke the method obtained from a call to @@ -214,8 +203,8 @@ public class MethodUtils { * * @param cls invoke static method on this class * @param methodName get method with this name - * @param args use these arguments - treat null as empty array - * @param parameterTypes match these parameters - treat null as empty array + * @param args use these arguments - treat {@code null} as empty array + * @param parameterTypes match these parameters - treat {@code null as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -228,12 +217,8 @@ public class MethodUtils { Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); final Method method = getAccessibleMethod(cls, methodName, parameterTypes); if (method == null) { throw new NoSuchMethodException("No such accessible method: " @@ -243,13 +228,13 @@ public class MethodUtils { } /** - *

Invokes a named static method whose parameter type matches the object type.

+ *

Invokes a named {@code static} method whose parameter type matches the object type.

* *

This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.

* *

This method supports calls to methods taking primitive parameters - * via passing in wrapping classes. So, for example, a Boolean class - * would match a boolean primitive.

+ * via passing in wrapping classes. So, for example, a {@code Boolean} class + * would match a {@code boolean} primitive.

* *

This is a convenient wrapper for * {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}. @@ -257,7 +242,7 @@ public class MethodUtils { * * @param cls invoke static method on this class * @param methodName get method with this name - * @param args use these arguments - treat null as empty array + * @param args use these arguments - treat {@code null} as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -269,27 +254,25 @@ public class MethodUtils { public static Object invokeStaticMethod(final Class cls, final String methodName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class[] parameterTypes = ClassUtils.toClass(args); return invokeStaticMethod(cls, methodName, args, parameterTypes); } /** - *

Invokes a named static method whose parameter type matches the object type.

+ *

Invokes a named {@code static} method whose parameter type matches the object type.

* *

This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.

* *

This method supports calls to methods taking primitive parameters - * via passing in wrapping classes. So, for example, a Boolean class - * would match a boolean primitive.

+ * via passing in wrapping classes. So, for example, a {@code Boolean} class + * would match a {@code boolean} primitive.

* * * @param cls invoke static method on this class * @param methodName get method with this name - * @param args use these arguments - treat null as empty array - * @param parameterTypes match these parameters - treat null as empty array + * @param args use these arguments - treat {@code null} as empty array + * @param parameterTypes match these parameters - treat {@code null} as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -302,12 +285,8 @@ public class MethodUtils { Object[] args, Class[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (parameterTypes == null) { - parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; - } - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); + parameterTypes = ArrayUtils.nullToEmpty(parameterTypes); final Method method = getMatchingAccessibleMethod(cls, methodName, parameterTypes); if (method == null) { @@ -318,7 +297,7 @@ public class MethodUtils { } /** - *

Invokes a static method whose parameter types match exactly the object + *

Invokes a {@code static} method whose parameter types match exactly the object * types.

* *

This uses reflection to invoke the method obtained from a call to @@ -326,7 +305,7 @@ public class MethodUtils { * * @param cls invoke static method on this class * @param methodName get method with this name - * @param args use these arguments - treat null as empty array + * @param args use these arguments - treat {@code null} as empty array * @return The value returned by the invoked method * * @throws NoSuchMethodException if there is no such accessible method @@ -338,19 +317,17 @@ public class MethodUtils { public static Object invokeExactStaticMethod(final Class cls, final String methodName, Object... args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - if (args == null) { - args = ArrayUtils.EMPTY_OBJECT_ARRAY; - } + args = ArrayUtils.nullToEmpty(args); final Class[] parameterTypes = ClassUtils.toClass(args); return invokeExactStaticMethod(cls, methodName, args, parameterTypes); } /** *

Returns an accessible method (that is, one that can be invoked via - * reflection) with given name and parameters. If no such method - * can be found, return null. - * This is just a convenient wrapper for - * {@link #getAccessibleMethod(Method method)}.

+ * reflection) with given name and parameters. If no such method + * can be found, return {@code null}. + * This is just a convenience wrapper for + * {@link #getAccessibleMethod(Method)}.

* * @param cls get method from this class * @param methodName get method with this name @@ -369,8 +346,8 @@ public class MethodUtils { /** *

Returns an accessible method (that is, one that can be invoked via - * reflection) that implements the specified Method. If no such method - * can be found, return null.

+ * reflection) that implements the specified Method. If no such method + * can be found, return {@code null}.

* * @param method The method that we wish to call * @return The accessible method @@ -402,12 +379,12 @@ public class MethodUtils { /** *

Returns an accessible method (that is, one that can be invoked via * reflection) by scanning through the superclasses. If no such method - * can be found, return null.

+ * can be found, return {@code null}.

* * @param cls Class to be checked * @param methodName Method name of the method we wish to call * @param parameterTypes The parameter type signatures - * @return the accessible method or null if not found + * @return the accessible method or {@code null} if not found */ private static Method getAccessibleMethodFromSuperclass(final Class cls, final String methodName, final Class... parameterTypes) { @@ -428,22 +405,20 @@ public class MethodUtils { /** *

Returns an accessible method (that is, one that can be invoked via * reflection) that implements the specified method, by scanning through - * all implemented interfaces and subinterfaces. If no such method - * can be found, return null.

+ * all implemented interfaces and subinterfaces. If no such method + * can be found, return {@code null}.

* - *

There isn't any good reason why this method must be private. + *

There isn't any good reason why this method must be {@code private}. * It is because there doesn't seem any reason why other classes should * call this rather than the higher level methods.

* * @param cls Parent class for the interfaces to be checked * @param methodName Method name of the method we wish to call * @param parameterTypes The parameter type signatures - * @return the accessible method or null if not found + * @return the accessible method or {@code null} if not found */ private static Method getAccessibleMethodFromInterfaceNest(Class cls, final String methodName, final Class... parameterTypes) { - Method method = null; - // Search up the superclass chain for (; cls != null; cls = cls.getSuperclass()) { @@ -456,7 +431,7 @@ public class MethodUtils { } // Does the method exist on this interface? try { - method = interfaces[i].getDeclaredMethod(methodName, + return interfaces[i].getDeclaredMethod(methodName, parameterTypes); } catch (final NoSuchMethodException e) { // NOPMD /* @@ -464,18 +439,15 @@ public class MethodUtils { * method returns null. */ } - if (method != null) { - break; - } // Recursively check our parent interfaces - method = getAccessibleMethodFromInterfaceNest(interfaces[i], + Method method = getAccessibleMethodFromInterfaceNest(interfaces[i], methodName, parameterTypes); if (method != null) { - break; + return method; } } } - return method; + return null; } /** @@ -490,7 +462,7 @@ public class MethodUtils { * #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}. * *

This method can match primitive parameter by passing in wrapper classes. - * For example, a Boolean will match a primitive boolean + * For example, a {@code Boolean} will match a primitive {@code boolean} * parameter. * * @param cls find method in this class @@ -531,8 +503,10 @@ public class MethodUtils { /** * Get the hierarchy of overridden methods down to {@code result} respecting generics. * @param method lowest to consider - * @param interfacesBehavior whether to search interfaces - * @return Collection in ascending order from sub- to superclass + * @param interfacesBehavior whether to search interfaces, {@code null} {@code implies} false + * @return Set in ascending order from sub- to superclass + * @throws NullPointerException if the specified method is {@code null} + * @since 3.2 */ public static Set getOverrideHierarchy(final Method method, Interfaces interfacesBehavior) { Validate.notNull(method); @@ -568,7 +542,6 @@ public class MethodUtils { } result.add(m); } - return result; }