From b2ad5e80bbed74153dd45a871041d04294c2bdb9 Mon Sep 17 00:00:00 2001
From: Matthew Jason Benson Utility reflection methods focused on constructors, modeled after
* {@link MethodUtils}. 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
- * 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. {@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. ConstructorUtils instances should NOT be constructed in standard
* programming. Instead, the class should be used as
- * Known Limitations
Accessing Public Constructors In A Default
- * Access Superclass
IllegalAccessException
is thrown if the constructors is
+ * Access Superclass ConstructorUtils
contains a workaround for this situation. It
- * will attempt to call setAccessible
on this constructor. If this
+ * 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. * * @paramcls
, 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 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 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 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 This simply ensures that the constructor is accessible.
* * @paramFirst 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 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 accessibleField
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 ListsetAccessible
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. *
* *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)
.
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.
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.
This uses reflection to invoke the method obtained from a call to
- * getAccessibleMethod()
.
This uses reflection to invoke the method obtained from a call to
- * getAccessibleMethod()
.
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.
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.
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)}.
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
.
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
.
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
.
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 ornull
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