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
This commit is contained in:
Matthew Jason Benson 2013-10-11 19:38:49 +00:00
parent eed09d6bd4
commit b2ad5e80bb
4 changed files with 316 additions and 349 deletions

View File

@ -16,26 +16,28 @@
*/ */
package org.apache.commons.lang3.reflect; package org.apache.commons.lang3.reflect;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.Validate;
/** /**
* <p> Utility reflection methods focused on constructors, modeled after * <p> Utility reflection methods focused on constructors, modeled after
* {@link MethodUtils}. </p> * {@link MethodUtils}. </p>
* *
* <h3>Known Limitations</h3> <h4>Accessing Public Constructors In A Default * <h3>Known Limitations</h3> <h4>Accessing Public Constructors In A Default
* Access Superclass</h4> <p>There is an issue when invoking public constructors * Access Superclass</h4> <p>There is an issue when invoking {@code public} constructors
* contained in a default access superclass. Reflection locates these * contained in a default access superclass. Reflection correctly locates these
* constructors fine and correctly assigns them as public. However, an * constructors and assigns them as {@code public}. However, an
* <code>IllegalAccessException</code> is thrown if the constructors is * {@link IllegalAccessException} is thrown if the constructor is
* invoked.</p> * invoked.</p>
* *
* <p><code>ConstructorUtils</code> contains a workaround for this situation. It * <p>{@link ConstructorUtils} contains a workaround for this situation: it
* will attempt to call <code>setAccessible</code> on this constructor. If this * 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 * 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 * succeed when the application has sufficient security privileges. If this call
* fails then a warning will be logged and the method may fail.</p> * fails then a warning will be logged and the method may fail.</p>
@ -48,9 +50,9 @@ public class ConstructorUtils {
/** /**
* <p>ConstructorUtils instances should NOT be constructed in standard * <p>ConstructorUtils instances should NOT be constructed in standard
* programming. Instead, the class should be used as * programming. Instead, the class should be used as
* <code>ConstructorUtils.invokeConstructor(cls, args)</code>.</p> * {@code ConstructorUtils.invokeConstructor(cls, args)}.</p>
* *
* <p>This constructor is public to permit tools that require a JavaBean * <p>This constructor is {@code public} to permit tools that require a JavaBean
* instance to operate.</p> * instance to operate.</p>
*/ */
public ConstructorUtils() { public ConstructorUtils() {
@ -65,10 +67,11 @@ public class ConstructorUtils {
* The constructor signature must match the argument types by assignment compatibility.</p> * The constructor signature must match the argument types by assignment compatibility.</p>
* *
* @param <T> the type to be constructed * @param <T> the type to be constructed
* @param cls the class to be constructed, not null * @param cls the class to be constructed, not {@code null}
* @param args the array of arguments, null treated as empty * @param args the array of arguments, {@code null treated as empty
* @return new instance of <code>cls</code>, not null * @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 NoSuchMethodException if a matching constructor cannot be found
* @throws IllegalAccessException if invocation is not permitted by security * @throws IllegalAccessException if invocation is not permitted by security
* @throws InvocationTargetException if an error occurs on invocation * @throws InvocationTargetException if an error occurs on invocation
@ -78,9 +81,7 @@ public class ConstructorUtils {
public static <T> T invokeConstructor(final Class<T> cls, Object... args) public static <T> T invokeConstructor(final Class<T> cls, Object... args)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException { InstantiationException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?> parameterTypes[] = ClassUtils.toClass(args); final Class<?> parameterTypes[] = ClassUtils.toClass(args);
return invokeConstructor(cls, args, parameterTypes); return invokeConstructor(cls, args, parameterTypes);
} }
@ -93,11 +94,12 @@ public class ConstructorUtils {
* The constructor signature must match the parameter types by assignment compatibility.</p> * The constructor signature must match the parameter types by assignment compatibility.</p>
* *
* @param <T> the type to be constructed * @param <T> the type to be constructed
* @param cls the class to be constructed, not null * @param cls the class to be constructed, not {@code null}
* @param args the array of arguments, null treated as empty * @param args the array of arguments, {@code null} treated as empty
* @param parameterTypes the array of parameter types, null treated as empty * @param parameterTypes the array of parameter types, {@code null} treated as empty
* @return new instance of <code>cls</code>, not null * @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 NoSuchMethodException if a matching constructor cannot be found
* @throws IllegalAccessException if invocation is not permitted by security * @throws IllegalAccessException if invocation is not permitted by security
* @throws InvocationTargetException if an error occurs on invocation * @throws InvocationTargetException if an error occurs on invocation
@ -107,12 +109,8 @@ public class ConstructorUtils {
public static <T> T invokeConstructor(final Class<T> cls, Object[] args, Class<?>[] parameterTypes) public static <T> T invokeConstructor(final Class<T> cls, Object[] args, Class<?>[] parameterTypes)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException { InstantiationException {
if (parameterTypes == null) { args = ArrayUtils.nullToEmpty(args);
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
}
if (args == null) {
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Constructor<T> ctor = getMatchingAccessibleConstructor(cls, parameterTypes); final Constructor<T> ctor = getMatchingAccessibleConstructor(cls, parameterTypes);
if (ctor == null) { if (ctor == null) {
throw new NoSuchMethodException( throw new NoSuchMethodException(
@ -129,10 +127,11 @@ public class ConstructorUtils {
* The constructor signature must match the argument types exactly.</p> * The constructor signature must match the argument types exactly.</p>
* *
* @param <T> the type to be constructed * @param <T> the type to be constructed
* @param cls the class to be constructed, not null * @param cls the class to be constructed, not {@code null}
* @param args the array of arguments, null treated as empty * @param args the array of arguments, {@code null treated as empty
* @return new instance of <code>cls</code>, not null * @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 NoSuchMethodException if a matching constructor cannot be found
* @throws IllegalAccessException if invocation is not permitted by security * @throws IllegalAccessException if invocation is not permitted by security
* @throws InvocationTargetException if an error occurs on invocation * @throws InvocationTargetException if an error occurs on invocation
@ -142,9 +141,7 @@ public class ConstructorUtils {
public static <T> T invokeExactConstructor(final Class<T> cls, Object... args) public static <T> T invokeExactConstructor(final Class<T> cls, Object... args)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
InstantiationException { InstantiationException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?> parameterTypes[] = ClassUtils.toClass(args); final Class<?> parameterTypes[] = ClassUtils.toClass(args);
return invokeExactConstructor(cls, args, parameterTypes); return invokeExactConstructor(cls, args, parameterTypes);
} }
@ -157,11 +154,12 @@ public class ConstructorUtils {
* The constructor signature must match the parameter types exactly.</p> * The constructor signature must match the parameter types exactly.</p>
* *
* @param <T> the type to be constructed * @param <T> the type to be constructed
* @param cls the class to be constructed, not null * @param cls the class to be constructed, not {@code null}
* @param args the array of arguments, null treated as empty * @param args the array of arguments, {@code null} treated as empty
* @param parameterTypes the array of parameter types, null treated as empty * @param parameterTypes the array of parameter types, {@code null} treated as empty
* @return new instance of <code>cls</code>, not null * @return new instance of <code>cls</code>, not {@code null}
* *
* @throws NullPointerException if {@code cls} is {@code null}
* @throws NoSuchMethodException if a matching constructor cannot be found * @throws NoSuchMethodException if a matching constructor cannot be found
* @throws IllegalAccessException if invocation is not permitted by security * @throws IllegalAccessException if invocation is not permitted by security
* @throws InvocationTargetException if an error occurs on invocation * @throws InvocationTargetException if an error occurs on invocation
@ -171,12 +169,8 @@ public class ConstructorUtils {
public static <T> T invokeExactConstructor(final Class<T> cls, Object[] args, public static <T> T invokeExactConstructor(final Class<T> cls, Object[] args,
Class<?>[] parameterTypes) throws NoSuchMethodException, IllegalAccessException, Class<?>[] parameterTypes) throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException { InvocationTargetException, InstantiationException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY; parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
}
if (parameterTypes == null) {
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
}
final Constructor<T> ctor = getAccessibleConstructor(cls, parameterTypes); final Constructor<T> ctor = getAccessibleConstructor(cls, parameterTypes);
if (ctor == null) { if (ctor == null) {
throw new NoSuchMethodException( throw new NoSuchMethodException(
@ -193,14 +187,16 @@ public class ConstructorUtils {
* The constructor signature must match the parameter types exactly.</p> * The constructor signature must match the parameter types exactly.</p>
* *
* @param <T> the constructor type * @param <T> 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 the array of parameter types, null treated as empty * @param parameterTypes the array of parameter types, {@code null} treated as empty
* @return the constructor, null if no matching accessible constructor found * @return the constructor, {@code null} if no matching accessible constructor found
* @see Class#getConstructor * @see Class#getConstructor
* @see #getAccessibleConstructor(java.lang.reflect.Constructor) * @see #getAccessibleConstructor(java.lang.reflect.Constructor)
* @throws NullPointerException if {@code cls} is {@code null}
*/ */
public static <T> Constructor<T> getAccessibleConstructor(final Class<T> cls, public static <T> Constructor<T> getAccessibleConstructor(final Class<T> cls,
final Class<?>... parameterTypes) { final Class<?>... parameterTypes) {
Validate.notNull(cls, "class cannot be null");
try { try {
return getAccessibleConstructor(cls.getConstructor(parameterTypes)); return getAccessibleConstructor(cls.getConstructor(parameterTypes));
} catch (final NoSuchMethodException e) { } catch (final NoSuchMethodException e) {
@ -214,11 +210,13 @@ public class ConstructorUtils {
* <p>This simply ensures that the constructor is accessible.</p> * <p>This simply ensures that the constructor is accessible.</p>
* *
* @param <T> the constructor type * @param <T> the constructor type
* @param ctor the prototype constructor object, not null * @param ctor the prototype constructor object, not {@code null}
* @return the constructor, null if no matching accessible constructor found * @return the constructor, {@code null} if no matching accessible constructor found
* @see java.lang.SecurityManager * @see java.lang.SecurityManager
* @throws NullPointerException if {@code ctor} is {@code null}
*/ */
public static <T> Constructor<T> getAccessibleConstructor(final Constructor<T> ctor) { public static <T> Constructor<T> getAccessibleConstructor(final Constructor<T> ctor) {
Validate.notNull(ctor, "constructor cannot be null");
return MemberUtils.isAccessible(ctor) return MemberUtils.isAccessible(ctor)
&& Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null; && Modifier.isPublic(ctor.getDeclaringClass().getModifiers()) ? ctor : null;
} }
@ -232,16 +230,18 @@ public class ConstructorUtils {
* *
* <p>First it checks if there is a constructor matching the exact signature. * <p>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 * If not then all the constructors of the class are checked to see if their
* signatures are assignment compatible with the parameter types. * signatures are assignment-compatible with the parameter types.
* The first assignment compatible matching constructor is returned.</p> * The first assignment-compatible matching constructor is returned.</p>
* *
* @param <T> the constructor type * @param <T> 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 * @param parameterTypes find method with compatible parameters
* @return the constructor, null if no matching accessible constructor found * @return the constructor, null if no matching accessible constructor found
* @throws NullPointerException if {@code cls} is {@code null}
*/ */
public static <T> Constructor<T> getMatchingAccessibleConstructor(final Class<T> cls, public static <T> Constructor<T> getMatchingAccessibleConstructor(final Class<T> cls,
final Class<?>... parameterTypes) { final Class<?>... parameterTypes) {
Validate.notNull(cls, "class cannot be null");
// see if we can find the constructor directly // see if we can find the constructor directly
// most of the time this works and it's much faster // most of the time this works and it's much faster
try { try {

View File

@ -16,15 +16,18 @@
*/ */
package org.apache.commons.lang3.reflect; package org.apache.commons.lang3.reflect;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.ClassUtils; 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. * component.
* <p> * <p>
* The ability is provided to break the scoping restrictions coded by the programmer. This can allow fields to be * 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 { public class FieldUtils {
/** /**
* FieldUtils instances should NOT be constructed in standard programming. * {@link FieldUtils} instances should NOT be constructed in standard programming.
* <p> * <p>
* 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.</p>
*/ */
public FieldUtils() { public FieldUtils() {
super(); super();
} }
/** /**
* Gets an accessible <code>Field</code> 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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) { public static Field getField(final Class<?> cls, final String fieldName) {
final Field field = getField(cls, fieldName, false); final Field field = getField(cls, fieldName, false);
@ -62,27 +65,24 @@ public class FieldUtils {
} }
/** /**
* Gets an accessible <code>Field</code> 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. * considered.
* *
* @param cls * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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) { public static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
if (cls == null) { Validate.isTrue(cls != null, "The class must not be null");
throw new IllegalArgumentException("The class must not be null"); Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
}
if (fieldName == null) {
throw new IllegalArgumentException("The field name must not be null");
}
// Sun Java 1.3 has a bugged implementation of getField hence we write the // Sun Java 1.3 has a bugged implementation of getField hence we write the
// code ourselves // code ourselves
@ -120,11 +120,9 @@ public class FieldUtils {
Field match = null; Field match = null;
for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) { for (final Class<?> class1 : ClassUtils.getAllInterfaces(cls)) {
try { try {
final Field test = ((Class<?>) class1).getField(fieldName); final Field test = class1.getField(fieldName);
if (match != null) { Validate.isTrue(match == null, "Reference to field %s is ambiguous relative to %s"
throw new IllegalArgumentException("Reference to field " + fieldName + " is ambiguous relative to " + cls + + "; a matching field exists on two or more implemented interfaces.", fieldName, cls);
"; a matching field exists on two or more implemented interfaces.");
}
match = test; match = test;
} catch (final NoSuchFieldException ex) { // NOPMD } catch (final NoSuchFieldException ex) { // NOPMD
// ignore // ignore
@ -134,42 +132,38 @@ public class FieldUtils {
} }
/** /**
* Gets an accessible <code>Field</code> 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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) { public static Field getDeclaredField(final Class<?> cls, final String fieldName) {
return getDeclaredField(cls, fieldName, false); return getDeclaredField(cls, fieldName, false);
} }
/** /**
* Gets an accessible <code>Field</code> 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. * considered.
* *
* @param cls * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. False will only * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* match public fields. * {@code false} will only match {@code public} fields.
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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) { public static Field getDeclaredField(final Class<?> cls, final String fieldName, final boolean forceAccess) {
if (cls == null) { Validate.isTrue(cls != null, "The class must not be null");
throw new IllegalArgumentException("The class must not be null"); Validate.isTrue(StringUtils.isNotBlank(fieldName), "The field name must not be blank/empty");
}
if (fieldName == null) {
throw new IllegalArgumentException("The field name must not be null");
}
try { try {
// only consider the specified class by using getDeclaredField() // only consider the specified class by using getDeclaredField()
final Field field = cls.getDeclaredField(fieldName); 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). * Gets all fields of the given class and its parents (if any).
* *
* @param cls * @param cls
* the class to query * the {@link Class} to query
* @return an array of Fields (maybe an empty array). * @return an array of Fields (possibly empty).
* @throws IllegalArgumentException
* if the class is {@code null}
* @since 3.2 * @since 3.2
*/ */
public static Field[] getAllFields(Class<?> cls) { 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). * Gets all fields of the given class and its parents (if any).
* *
* @param cls * @param cls
* the class to query * the {@link Class} to query
* @return an array of Fields (maybe an empty array). * @return an array of Fields (possibly empty).
* @throws IllegalArgumentException
* if the class is {@code null}
* @since 3.2 * @since 3.2
*/ */
public static List<Field> getAllFieldsList(Class<?> cls) { public static List<Field> getAllFieldsList(Class<?> cls) {
if (cls == null) { Validate.isTrue(cls != null, "The class must not be null");
throw new IllegalArgumentException("The class must not be null"); final List<Field> allFields = new ArrayList<Field>();
}
List<Field> allFields = new ArrayList<Field>();
Class<?> currentClass = cls; Class<?> currentClass = cls;
while (currentClass != null) { while (currentClass != null) {
final Field[] declaredFields = currentClass.getDeclaredFields(); 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 * @param field
* to read * to read
* @return the field value * @return the field value
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the field is null or not static * if the field is {@code null}, or not {@code static}
* @throws IllegalAccessException * @throws IllegalAccessException
* if the field is not accessible * if the field is not accessible
*/ */
@ -240,38 +236,35 @@ public class FieldUtils {
} }
/** /**
* Reads a static Field. * Reads a static {@link Field}.
* *
* @param field * @param field
* to read * to read
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* @return the field value * @return the field value
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the field is null or not static * if the field is {@code null} or not {@code static}
* @throws IllegalAccessException * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException { public static Object readStaticField(final Field field, final boolean forceAccess) throws IllegalAccessException {
if (field == null) { Validate.isTrue(field != null, "The field must not be null");
throw new IllegalArgumentException("The field must not be null"); Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field '%s' is not static", field.getName());
}
if (!Modifier.isStatic(field.getModifiers())) {
throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
}
return readField(field, (Object) null, forceAccess); 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the value of the field * @return the value of the field
* @throws IllegalArgumentException * @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 * @throws IllegalAccessException
* if the field is not accessible * 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(false)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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 * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { public static Object readStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
final Field field = getField(cls, fieldName, forceAccess); final Field field = getField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate field '%s' on %s", fieldName, cls);
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
return readStaticField(field, false); 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the value of the field * @return the value of the field
* @throws IllegalArgumentException * @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 * @throws IllegalAccessException
* if the field is not accessible * 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 * @param cls
* the class to reflect, must not be null * the {@link Class} to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @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 * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException { public static Object readDeclaredStaticField(final Class<?> cls, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
final Field field = getDeclaredField(cls, fieldName, forceAccess); final Field field = getDeclaredField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
return readStaticField(field, false); return readStaticField(field, false);
} }
/** /**
* Reads an accessible Field. * Reads an accessible {@link Field}.
* *
* @param field * @param field
* the field to use * the field to use
* @param target * @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 * @return the field value
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the field is null * if the field is {@code null}
* @throws IllegalAccessException * @throws IllegalAccessException
* if the field is not accessible * if the field is not accessible
*/ */
@ -364,24 +358,22 @@ public class FieldUtils {
} }
/** /**
* Reads a Field. * Reads a {@link Field}.
* *
* @param field * @param field
* the field to use * the field to use
* @param target * @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 * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* @return the field value * @return the field value
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the field is null * if the field is {@code null}
* @throws IllegalAccessException * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException { public static Object readField(final Field field, final Object target, final boolean forceAccess) throws IllegalAccessException {
if (field == null) { Validate.isTrue(field != null, "The field must not be null");
throw new IllegalArgumentException("The field must not be null");
}
if (forceAccess && !field.isAccessible()) { if (forceAccess && !field.isAccessible()) {
field.setAccessible(true); field.setAccessible(true);
} else { } 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the value of the field * @return the value of the field
* @throws IllegalArgumentException * @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 * @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 { public static Object readField(final Object target, final String fieldName) throws IllegalAccessException {
return readField(target, fieldName, false); return readField(target, fieldName, false);
} }
/** /**
* Reads the named field. Superclasses will be considered. * Reads the named {@link Field}. Superclasses will be considered.
* *
* @param target * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @return the field value * @return the field value
* @throws IllegalArgumentException * @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 * @throws IllegalAccessException
* if the named field is not made accessible * if the named field is not made accessible
*/ */
public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { public static Object readField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
if (target == null) { Validate.isTrue(target != null, "target object must not be null");
throw new IllegalArgumentException("target object must not be null");
}
final Class<?> cls = target.getClass(); final Class<?> cls = target.getClass();
final Field field = getField(cls, fieldName, forceAccess); final Field field = getField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate field %s on %s" , fieldName, cls);
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
return readField(field, target); 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @return the value of the field * @return the value of the field
* @throws IllegalArgumentException * @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 * @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 { public static Object readDeclaredField(final Object target, final String fieldName) throws IllegalAccessException {
return readDeclaredField(target, fieldName, false); return readDeclaredField(target, fieldName, false);
} }
/** /**
* <p<>Gets a Field value by name. Only the class of the specified object will be considered. * <p<>Gets a {@link Field} value by name. Only the class of the specified object will be considered.
* *
* @param target * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match public fields.
* @return the Field object * @return the Field object
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if <code>target</code> or <code>fieldName</code> is null * if {@code target} is {@code null}, or
* the field name is blank or empty or could not be found
* @throws IllegalAccessException * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException { public static Object readDeclaredField(final Object target, final String fieldName, final boolean forceAccess) throws IllegalAccessException {
if (target == null) { Validate.isTrue(target != null, "target object must not be null");
throw new IllegalArgumentException("target object must not be null");
}
final Class<?> cls = target.getClass(); final Class<?> cls = target.getClass();
final Field field = getDeclaredField(cls, fieldName, forceAccess); final Field field = getDeclaredField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate declared field %s.%s" , cls, fieldName);
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
return readField(field, target); return readField(field, target);
} }
/** /**
* Writes a public static Field. * Writes a {@code public static} {@link Field}.
* *
* @param field * @param field
* to write * to write
* @param value * @param value
* to set * to set
* @throws IllegalArgumentException * @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 * @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 { public static void writeStaticField(final Field field, final Object value) throws IllegalAccessException {
writeStaticField(field, value, false); writeStaticField(field, value, false);
} }
/** /**
* Writes a static Field. * Writes a static {@link Field}.
* *
* @param field * @param field
* to write * to write
* @param value * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. {@code false}
* will only match public fields. * will only match {@code public} fields.
* @throws IllegalArgumentException * @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 * @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 { public static void writeStaticField(final Field field, final Object value, final boolean forceAccess) throws IllegalAccessException {
if (field == null) { Validate.isTrue(field != null, "The field must not be null");
throw new IllegalArgumentException("The field must not be null"); Validate.isTrue(Modifier.isStatic(field.getModifiers()), "The field %s.%s is not static",
} field.getDeclaringClass().getName(), field.getName());
if (!Modifier.isStatic(field.getModifiers())) {
throw new IllegalArgumentException("The field '" + field.getName() + "' is not static");
}
writeField(field, (Object) null, value, forceAccess); 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 * @param cls
* Class on which the Field is to be found * {@link Class} on which the field is to be found
* @param fieldName * @param fieldName
* to write * to write
* @param value * @param value
* to set * to set
* @throws IllegalArgumentException * @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 * @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 { public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
writeStaticField(cls, fieldName, value, false); 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 * @param cls
* Class on which the Field is to be found * {@link Class} on which the field is to be found
* @param fieldName * @param fieldName
* to write * to write
* @param value * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @throws IllegalArgumentException * @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 * @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) public static void writeStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
throws IllegalAccessException { throws IllegalAccessException {
final Field field = getField(cls, fieldName, forceAccess); final Field field = getField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate field %s on %s", fieldName, cls);
throw new IllegalArgumentException("Cannot locate field " + fieldName + " on " + cls);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
writeStaticField(field, value); 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 * @param cls
* Class on which the Field is to be found * {@link Class} on which the field is to be found
* @param fieldName * @param fieldName
* to write * to write
* @param value * @param value
* to set * to set
* @throws IllegalArgumentException * @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 * @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 { public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value) throws IllegalAccessException {
writeDeclaredStaticField(cls, fieldName, value, false); 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 * @param cls
* Class on which the Field is to be found * {@link Class} on which the field is to be found
* @param fieldName * @param fieldName
* to write * to write
* @param value * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@code AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @throws IllegalArgumentException * @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 * @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) public static void writeDeclaredStaticField(final Class<?> cls, final String fieldName, final Object value, final boolean forceAccess)
throws IllegalAccessException { throws IllegalAccessException {
final Field field = getDeclaredField(cls, fieldName, forceAccess); final Field field = getDeclaredField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
writeField(field, (Object) null, value); writeField(field, (Object) null, value);
} }
/** /**
* Writes an accessible field. * Writes an accessible {@link Field}.
* *
* @param field * @param field
* to write * to write
* @param target * @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 * @param value
* to set * to set
* @throws IllegalArgumentException
* if the field is null
* @throws IllegalAccessException * @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 { public static void writeField(final Field field, final Object target, final Object value) throws IllegalAccessException {
writeField(field, target, value, false); writeField(field, target, value, false);
} }
/** /**
* Writes a field. * Writes a {@link Field}.
* *
* @param field * @param field
* to write * to write
* @param target * @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 * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the field is null * if the field is {@code null} or
* {@code value} is not assignable
* @throws IllegalAccessException * @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) public static void writeField(final Field field, final Object target, final Object value, final boolean forceAccess)
throws IllegalAccessException { throws IllegalAccessException {
if (field == null) { Validate.isTrue(field != null, "The field must not be null");
throw new IllegalArgumentException("The field must not be null");
}
if (forceAccess && !field.isAccessible()) { if (forceAccess && !field.isAccessible()) {
field.setAccessible(true); field.setAccessible(true);
} else { } 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param value * @param value
* to set * to set
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if <code>target</code> or <code>fieldName</code> 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 * @throws IllegalAccessException
* if the field is not accessible * 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param value * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method. {@code false}
* will only match public fields. * will only match {@code public} fields.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if <code>target</code> or <code>fieldName</code> 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 * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess) public static void writeField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
throws IllegalAccessException { throws IllegalAccessException {
if (target == null) { Validate.isTrue(target != null, "target object must not be null");
throw new IllegalArgumentException("target object must not be null");
}
final Class<?> cls = target.getClass(); final Class<?> cls = target.getClass();
final Field field = getField(cls, fieldName, forceAccess); final Field field = getField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
writeField(field, target, value); 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param value * @param value
* to set * to set
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if <code>target</code> or <code>fieldName</code> 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 * @throws IllegalAccessException
* if the field is not made accessible * 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 * @param target
* the object to reflect, must not be null * the object to reflect, must not be {@code null}
* @param fieldName * @param fieldName
* the field name to obtain * the field name to obtain
* @param value * @param value
* to set * to set
* @param forceAccess * @param forceAccess
* whether to break scope restrictions using the <code>setAccessible</code> method. <code>False</code> * whether to break scope restrictions using the {@link AccessibleObject#setAccessible(boolean)} method.
* will only match public fields. * {@code false} will only match {@code public} fields.
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if <code>target</code> or <code>fieldName</code> 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 * @throws IllegalAccessException
* if the field is not made accessible * if the field is not made accessible
*/ */
public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess) public static void writeDeclaredField(final Object target, final String fieldName, final Object value, final boolean forceAccess)
throws IllegalAccessException { throws IllegalAccessException {
if (target == null) { Validate.isTrue(target != null, "target object must not be null");
throw new IllegalArgumentException("target object must not be null");
}
final Class<?> cls = target.getClass(); final Class<?> cls = target.getClass();
final Field field = getDeclaredField(cls, fieldName, forceAccess); final Field field = getDeclaredField(cls, fieldName, forceAccess);
if (field == null) { Validate.isTrue(field != null, "Cannot locate declared field %s.%s", cls.getName(), fieldName);
throw new IllegalArgumentException("Cannot locate declared field " + cls.getName() + "." + fieldName);
}
// already forced access above, don't repeat it here: // already forced access above, don't repeat it here:
writeField(field, target, value); writeField(field, target, value);
} }

View File

@ -23,8 +23,8 @@ import java.lang.reflect.Modifier;
import org.apache.commons.lang3.ClassUtils; import org.apache.commons.lang3.ClassUtils;
/** /**
* Contains common code for working with Methods/Constructors, extracted and * Contains common code for working with {@link Method}s/{@link Constructor}s, extracted and
* refactored from <code>MethodUtils</code> when it was imported from Commons * refactored from {@link MethodUtils} when it was imported from Commons
* BeanUtils. * BeanUtils.
* *
* @since 2.5 * @since 2.5
@ -42,11 +42,11 @@ abstract class MemberUtils {
/** /**
* XXX Default access superclass workaround * 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. * these members are accessible. Calling them from compiled code works fine.
* Unfortunately, on some JVMs, using reflection to invoke these members * Unfortunately, on some JVMs, using reflection to invoke these members
* seems to (wrongly) prevent access even when the modifier is public. * seems to (wrongly) prevent access even when the modifier is {@code public}.
* Calling setAccessible(true) solves the problem but will only work from * Calling {@code setAccessible(true)} solves the problem but will only work from
* sufficiently privileged code. Better workarounds would be gratefully * sufficiently privileged code. Better workarounds would be gratefully
* accepted. * accepted.
* @param o the AccessibleObject to set as accessible * @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. * Returns whether a given set of modifiers implies package access.
* @param modifiers to test * @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) { static boolean isPackageAccess(final int modifiers) {
return (modifiers & ACCESS_TEST) == 0; return (modifiers & ACCESS_TEST) == 0;
} }
/** /**
* Returns whether a Member is accessible. * Returns whether a {@link Member} is accessible.
* @param m Member to check * @param m Member to check
* @return true if <code>m</code> is accessible * @return {@code true} if <code>m</code> is accessible
*/ */
static boolean isAccessible(final Member m) { static boolean isAccessible(final Member m) {
return m != null && Modifier.isPublic(m.getModifiers()) && !m.isSynthetic(); return m != null && Modifier.isPublic(m.getModifiers()) && !m.isSynthetic();
@ -93,8 +93,8 @@ abstract class MemberUtils {
* @param left the "left" parameter set * @param left the "left" parameter set
* @param right the "right" parameter set * @param right the "right" parameter set
* @param actual the runtime parameter types to match against * @param actual the runtime parameter types to match against
* <code>left</code>/<code>right</code> * {@code left}/{@code right}
* @return int consistent with <code>compare</code> semantics * @return int consistent with {@code compare} semantics
*/ */
static int compareParameterTypes(final Class<?>[] left, final Class<?>[] right, final Class<?>[] actual) { static int compareParameterTypes(final Class<?>[] left, final Class<?>[] right, final Class<?>[] actual) {
final float leftCost = getTotalTransformationCost(actual, left); final float leftCost = getTotalTransformationCost(actual, left);

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.commons.lang3.reflect; package org.apache.commons.lang3.reflect;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -33,19 +34,19 @@ import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.ClassUtils.Interfaces; import org.apache.commons.lang3.ClassUtils.Interfaces;
/** /**
* <p>Utility reflection methods focused on methods, originally from Commons BeanUtils. * <p>Utility reflection methods focused on {@link Method}s, originally from Commons BeanUtils.
* Differences from the BeanUtils version may be noted, especially where similar functionality * Differences from the BeanUtils version may be noted, especially where similar functionality
* already existed within Lang. * already existed within Lang.
* </p> * </p>
* *
* <h3>Known Limitations</h3> * <h3>Known Limitations</h3>
* <h4>Accessing Public Methods In A Default Access Superclass</h4> * <h4>Accessing Public Methods In A Default Access Superclass</h4>
* <p>There is an issue when invoking public methods contained in a default access superclass on JREs prior to 1.4. * <p>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 public. * Reflection locates these methods fine and correctly assigns them as {@code public}.
* However, an <code>IllegalAccessException</code> is thrown if the method is invoked.</p> * However, an {@link IllegalAccessException} is thrown if the method is invoked.</p>
* *
* <p><code>MethodUtils</code> contains a workaround for this situation. * <p>{@link MethodUtils} contains a workaround for this situation.
* It will attempt to call <code>setAccessible</code> on this method. * It will attempt to call {@link AccessibleObject#setAccessible(boolean)} on this method.
* If this call succeeds, then the method can be invoked as normal. * If this call succeeds, then the method can be invoked as normal.
* This call will only succeed when the application has sufficient security privileges. * This call will only succeed when the application has sufficient security privileges.
* If this call fails then the method may fail.</p> * If this call fails then the method may fail.</p>
@ -56,11 +57,11 @@ import org.apache.commons.lang3.ClassUtils.Interfaces;
public class MethodUtils { public class MethodUtils {
/** /**
* <p>MethodUtils instances should NOT be constructed in standard programming. * <p>{@link MethodUtils} instances should NOT be constructed in standard programming.
* Instead, the class should be used as * Instead, the class should be used as
* <code>MethodUtils.getAccessibleMethod(method)</code>.</p> * {@code MethodUtils.getAccessibleMethod(method)}.</p>
* *
* <p>This constructor is public to permit tools that require a JavaBean * <p>This constructor is {@code public} to permit tools that require a JavaBean
* instance to operate.</p> * instance to operate.</p>
*/ */
public MethodUtils() { public MethodUtils() {
@ -73,8 +74,8 @@ public class MethodUtils {
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p> * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
* *
* <p>This method supports calls to methods taking primitive parameters * <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> object * via passing in wrapping classes. So, for example, a {@code Boolean} object
* would match a <code>boolean</code> primitive.</p> * would match a {@code boolean} primitive.</p>
* *
* <p>This is a convenient wrapper for * <p>This is a convenient wrapper for
* {@link #invokeMethod(Object object,String methodName, Object[] args, Class[] parameterTypes)}. * {@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, public static Object invokeMethod(final Object object, final String methodName,
Object... args) throws NoSuchMethodException, Object... args) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException { IllegalAccessException, InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?>[] parameterTypes = ClassUtils.toClass(args); final Class<?>[] parameterTypes = ClassUtils.toClass(args);
return invokeMethod(object, methodName, args, parameterTypes); return invokeMethod(object, methodName, args, parameterTypes);
} }
@ -105,8 +104,8 @@ public class MethodUtils {
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p> * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
* *
* <p>This method supports calls to methods taking primitive parameters * <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> object * via passing in wrapping classes. So, for example, a {@code Boolean} object
* would match a <code>boolean</code> primitive.</p> * would match a {@code boolean} primitive.</p>
* *
* @param object invoke method on this object * @param object invoke method on this object
* @param methodName get method with this name * @param methodName get method with this name
@ -122,12 +121,8 @@ public class MethodUtils {
Object[] args, Class<?>[] parameterTypes) Object[] args, Class<?>[] parameterTypes)
throws NoSuchMethodException, IllegalAccessException, throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException { InvocationTargetException {
if (parameterTypes == null) { parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; args = ArrayUtils.nullToEmpty(args);
}
if (args == null) {
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Method method = getMatchingAccessibleMethod(object.getClass(), final Method method = getMatchingAccessibleMethod(object.getClass(),
methodName, parameterTypes); methodName, parameterTypes);
if (method == null) { if (method == null) {
@ -143,11 +138,11 @@ public class MethodUtils {
* types.</p> * types.</p>
* *
* <p>This uses reflection to invoke the method obtained from a call to * <p>This uses reflection to invoke the method obtained from a call to
* <code>getAccessibleMethod()</code>.</p> * {@link #getAccessibleMethod}(Class,String,Class[])}.</p>
* *
* @param object invoke method on this object * @param object invoke method on this object
* @param methodName get method with this name * @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible 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, public static Object invokeExactMethod(final Object object, final String methodName,
Object... args) throws NoSuchMethodException, Object... args) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException { IllegalAccessException, InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?>[] parameterTypes = ClassUtils.toClass(args); final Class<?>[] parameterTypes = ClassUtils.toClass(args);
return invokeExactMethod(object, methodName, args, parameterTypes); return invokeExactMethod(object, methodName, args, parameterTypes);
} }
@ -171,12 +164,12 @@ public class MethodUtils {
* types given.</p> * types given.</p>
* *
* <p>This uses reflection to invoke the method obtained from a call to * <p>This uses reflection to invoke the method obtained from a call to
* <code>getAccessibleMethod()</code>.</p> * {@link #getAccessibleMethod(Class,String,Class[])}.</p>
* *
* @param object invoke method on this object * @param object invoke method on this object
* @param methodName get method with this name * @param methodName get method with this name
* @param args use these arguments - treat null as empty array * @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible method * @throws NoSuchMethodException if there is no such accessible method
@ -189,12 +182,8 @@ public class MethodUtils {
Object[] args, Class<?>[] parameterTypes) Object[] args, Class<?>[] parameterTypes)
throws NoSuchMethodException, IllegalAccessException, throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException { InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY; parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
}
if (parameterTypes == null) {
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
}
final Method method = getAccessibleMethod(object.getClass(), methodName, final Method method = getAccessibleMethod(object.getClass(), methodName,
parameterTypes); parameterTypes);
if (method == null) { if (method == null) {
@ -206,7 +195,7 @@ public class MethodUtils {
} }
/** /**
* <p>Invokes a static method whose parameter types match exactly the parameter * <p>Invokes a {@code static} method whose parameter types match exactly the parameter
* types given.</p> * types given.</p>
* *
* <p>This uses reflection to invoke the method obtained from a call to * <p>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 cls invoke static method on this class
* @param methodName get method with this name * @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
* @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible method * @throws NoSuchMethodException if there is no such accessible method
@ -228,12 +217,8 @@ public class MethodUtils {
Object[] args, Class<?>[] parameterTypes) Object[] args, Class<?>[] parameterTypes)
throws NoSuchMethodException, IllegalAccessException, throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException { InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY; parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
}
if (parameterTypes == null) {
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
}
final Method method = getAccessibleMethod(cls, methodName, parameterTypes); final Method method = getAccessibleMethod(cls, methodName, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException("No such accessible method: " throw new NoSuchMethodException("No such accessible method: "
@ -243,13 +228,13 @@ public class MethodUtils {
} }
/** /**
* <p>Invokes a named static method whose parameter type matches the object type.</p> * <p>Invokes a named {@code static} method whose parameter type matches the object type.</p>
* *
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p> * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
* *
* <p>This method supports calls to methods taking primitive parameters * <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class * via passing in wrapping classes. So, for example, a {@code Boolean} class
* would match a <code>boolean</code> primitive.</p> * would match a {@code boolean} primitive.</p>
* *
* <p>This is a convenient wrapper for * <p>This is a convenient wrapper for
* {@link #invokeStaticMethod(Class objectClass,String methodName,Object [] args,Class[] parameterTypes)}. * {@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 cls invoke static method on this class
* @param methodName get method with this name * @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible 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, public static Object invokeStaticMethod(final Class<?> cls, final String methodName,
Object... args) throws NoSuchMethodException, Object... args) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException { IllegalAccessException, InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?>[] parameterTypes = ClassUtils.toClass(args); final Class<?>[] parameterTypes = ClassUtils.toClass(args);
return invokeStaticMethod(cls, methodName, args, parameterTypes); return invokeStaticMethod(cls, methodName, args, parameterTypes);
} }
/** /**
* <p>Invokes a named static method whose parameter type matches the object type.</p> * <p>Invokes a named {@code static} method whose parameter type matches the object type.</p>
* *
* <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p> * <p>This method delegates the method search to {@link #getMatchingAccessibleMethod(Class, String, Class[])}.</p>
* *
* <p>This method supports calls to methods taking primitive parameters * <p>This method supports calls to methods taking primitive parameters
* via passing in wrapping classes. So, for example, a <code>Boolean</code> class * via passing in wrapping classes. So, for example, a {@code Boolean} class
* would match a <code>boolean</code> primitive.</p> * would match a {@code boolean} primitive.</p>
* *
* *
* @param cls invoke static method on this class * @param cls invoke static method on this class
* @param methodName get method with this name * @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
* @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible method * @throws NoSuchMethodException if there is no such accessible method
@ -302,12 +285,8 @@ public class MethodUtils {
Object[] args, Class<?>[] parameterTypes) Object[] args, Class<?>[] parameterTypes)
throws NoSuchMethodException, IllegalAccessException, throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException { InvocationTargetException {
if (parameterTypes == null) { args = ArrayUtils.nullToEmpty(args);
parameterTypes = ArrayUtils.EMPTY_CLASS_ARRAY; parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
}
if (args == null) {
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Method method = getMatchingAccessibleMethod(cls, methodName, final Method method = getMatchingAccessibleMethod(cls, methodName,
parameterTypes); parameterTypes);
if (method == null) { if (method == null) {
@ -318,7 +297,7 @@ public class MethodUtils {
} }
/** /**
* <p>Invokes a static method whose parameter types match exactly the object * <p>Invokes a {@code static} method whose parameter types match exactly the object
* types.</p> * types.</p>
* *
* <p>This uses reflection to invoke the method obtained from a call to * <p>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 cls invoke static method on this class
* @param methodName get method with this name * @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 * @return The value returned by the invoked method
* *
* @throws NoSuchMethodException if there is no such accessible method * @throws NoSuchMethodException if there is no such accessible method
@ -338,9 +317,7 @@ public class MethodUtils {
public static Object invokeExactStaticMethod(final Class<?> cls, final String methodName, public static Object invokeExactStaticMethod(final Class<?> cls, final String methodName,
Object... args) throws NoSuchMethodException, Object... args) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException { IllegalAccessException, InvocationTargetException {
if (args == null) { args = ArrayUtils.nullToEmpty(args);
args = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
final Class<?>[] parameterTypes = ClassUtils.toClass(args); final Class<?>[] parameterTypes = ClassUtils.toClass(args);
return invokeExactStaticMethod(cls, methodName, args, parameterTypes); return invokeExactStaticMethod(cls, methodName, args, parameterTypes);
} }
@ -348,9 +325,9 @@ public class MethodUtils {
/** /**
* <p>Returns an accessible method (that is, one that can be invoked via * <p>Returns an accessible method (that is, one that can be invoked via
* reflection) with given name and parameters. If no such method * reflection) with given name and parameters. If no such method
* can be found, return <code>null</code>. * can be found, return {@code null}.
* This is just a convenient wrapper for * This is just a convenience wrapper for
* {@link #getAccessibleMethod(Method method)}.</p> * {@link #getAccessibleMethod(Method)}.</p>
* *
* @param cls get method from this class * @param cls get method from this class
* @param methodName get method with this name * @param methodName get method with this name
@ -370,7 +347,7 @@ public class MethodUtils {
/** /**
* <p>Returns an accessible method (that is, one that can be invoked via * <p>Returns an accessible method (that is, one that can be invoked via
* reflection) that implements the specified Method. If no such method * reflection) that implements the specified Method. If no such method
* can be found, return <code>null</code>.</p> * can be found, return {@code null}.</p>
* *
* @param method The method that we wish to call * @param method The method that we wish to call
* @return The accessible method * @return The accessible method
@ -402,12 +379,12 @@ public class MethodUtils {
/** /**
* <p>Returns an accessible method (that is, one that can be invoked via * <p>Returns an accessible method (that is, one that can be invoked via
* reflection) by scanning through the superclasses. If no such method * reflection) by scanning through the superclasses. If no such method
* can be found, return <code>null</code>.</p> * can be found, return {@code null}.</p>
* *
* @param cls Class to be checked * @param cls Class to be checked
* @param methodName Method name of the method we wish to call * @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures * @param parameterTypes The parameter type signatures
* @return the accessible method or <code>null</code> if not found * @return the accessible method or {@code null} if not found
*/ */
private static Method getAccessibleMethodFromSuperclass(final Class<?> cls, private static Method getAccessibleMethodFromSuperclass(final Class<?> cls,
final String methodName, final Class<?>... parameterTypes) { final String methodName, final Class<?>... parameterTypes) {
@ -429,21 +406,19 @@ public class MethodUtils {
* <p>Returns an accessible method (that is, one that can be invoked via * <p>Returns an accessible method (that is, one that can be invoked via
* reflection) that implements the specified method, by scanning through * reflection) that implements the specified method, by scanning through
* all implemented interfaces and subinterfaces. If no such method * all implemented interfaces and subinterfaces. If no such method
* can be found, return <code>null</code>.</p> * can be found, return {@code null}.</p>
* *
* <p>There isn't any good reason why this method must be private. * <p>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 * It is because there doesn't seem any reason why other classes should
* call this rather than the higher level methods.</p> * call this rather than the higher level methods.</p>
* *
* @param cls Parent class for the interfaces to be checked * @param cls Parent class for the interfaces to be checked
* @param methodName Method name of the method we wish to call * @param methodName Method name of the method we wish to call
* @param parameterTypes The parameter type signatures * @param parameterTypes The parameter type signatures
* @return the accessible method or <code>null</code> if not found * @return the accessible method or {@code null} if not found
*/ */
private static Method getAccessibleMethodFromInterfaceNest(Class<?> cls, private static Method getAccessibleMethodFromInterfaceNest(Class<?> cls,
final String methodName, final Class<?>... parameterTypes) { final String methodName, final Class<?>... parameterTypes) {
Method method = null;
// Search up the superclass chain // Search up the superclass chain
for (; cls != null; cls = cls.getSuperclass()) { for (; cls != null; cls = cls.getSuperclass()) {
@ -456,7 +431,7 @@ public class MethodUtils {
} }
// Does the method exist on this interface? // Does the method exist on this interface?
try { try {
method = interfaces[i].getDeclaredMethod(methodName, return interfaces[i].getDeclaredMethod(methodName,
parameterTypes); parameterTypes);
} catch (final NoSuchMethodException e) { // NOPMD } catch (final NoSuchMethodException e) { // NOPMD
/* /*
@ -464,19 +439,16 @@ public class MethodUtils {
* method returns null. * method returns null.
*/ */
} }
if (method != null) {
break;
}
// Recursively check our parent interfaces // Recursively check our parent interfaces
method = getAccessibleMethodFromInterfaceNest(interfaces[i], Method method = getAccessibleMethodFromInterfaceNest(interfaces[i],
methodName, parameterTypes); methodName, parameterTypes);
if (method != null) { if (method != null) {
break;
}
}
}
return method; return method;
} }
}
}
return null;
}
/** /**
* <p>Finds an accessible method that matches the given name and has compatible parameters. * <p>Finds an accessible method that matches the given name and has compatible parameters.
@ -490,7 +462,7 @@ public class MethodUtils {
* #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}. * #invokeMethod(Object object, String methodName, Object[] args, Class[] parameterTypes)}.
* *
* <p>This method can match primitive parameter by passing in wrapper classes. * <p>This method can match primitive parameter by passing in wrapper classes.
* For example, a <code>Boolean</code> will match a primitive <code>boolean</code> * For example, a {@code Boolean} will match a primitive {@code boolean}
* parameter. * parameter.
* *
* @param cls find method in this class * @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. * Get the hierarchy of overridden methods down to {@code result} respecting generics.
* @param method lowest to consider * @param method lowest to consider
* @param interfacesBehavior whether to search interfaces * @param interfacesBehavior whether to search interfaces, {@code null} {@code implies} false
* @return Collection<Method> in ascending order from sub- to superclass * @return Set<Method> in ascending order from sub- to superclass
* @throws NullPointerException if the specified method is {@code null}
* @since 3.2
*/ */
public static Set<Method> getOverrideHierarchy(final Method method, Interfaces interfacesBehavior) { public static Set<Method> getOverrideHierarchy(final Method method, Interfaces interfacesBehavior) {
Validate.notNull(method); Validate.notNull(method);
@ -568,7 +542,6 @@ public class MethodUtils {
} }
result.add(m); result.add(m);
} }
return result; return result;
} }