LANG-1115: Add support for varargs in ConstructorUtils, MemberUtils, and MethodUtils
This closes #89 from github.
This commit is contained in:
parent
77d187eefc
commit
5e62bf80f3
|
@ -22,6 +22,7 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="3.5" date="tba" description="tba">
|
<release version="3.5" date="tba" description="tba">
|
||||||
|
<action issue="LANG-1115" type="add" dev="chas" due-to="Jim Lloyd, Joe Ferner">Add support for varargs in ConstructorUtils, MemberUtils, and MethodUtils</action>
|
||||||
<action issue="LANG-1134" type="add" dev="chas" due-to="Alan Smithee">New methods for lang3.Validate</action>
|
<action issue="LANG-1134" type="add" dev="chas" due-to="Alan Smithee">New methods for lang3.Validate</action>
|
||||||
<action issue="LANG-1222" type="fix" dev="ggregory" due-to="Adam J.">Fix for incorrect comment on StringUtils.containsIgnoreCase method</action>
|
<action issue="LANG-1222" type="fix" dev="ggregory" due-to="Adam J.">Fix for incorrect comment on StringUtils.containsIgnoreCase method</action>
|
||||||
<action issue="LANG-1221" type="fix" dev="ggregory" due-to="Pierre Templier">Fix typo on appendIfMissing javadoc</action>
|
<action issue="LANG-1221" type="fix" dev="ggregory" due-to="Pierre Templier">Fix typo on appendIfMissing javadoc</action>
|
||||||
|
|
|
@ -4692,6 +4692,39 @@ public class ArrayUtils {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Create an array of primitive type from an array of wrapper types.
|
||||||
|
*
|
||||||
|
* <p>This method returns {@code null} for a {@code null} input array.
|
||||||
|
*
|
||||||
|
* @param array an array of wrapper object
|
||||||
|
* @return an array of the corresponding primitive type, or the original array
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
public static Object toPrimitive(final Object array) {
|
||||||
|
if (array == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Class<?> ct = array.getClass().getComponentType();
|
||||||
|
Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
|
||||||
|
if(Integer.TYPE.equals(pt)) {
|
||||||
|
return toPrimitive((Integer[]) array);
|
||||||
|
}
|
||||||
|
if(Long.TYPE.equals(pt)) {
|
||||||
|
return toPrimitive((Long[]) array);
|
||||||
|
}
|
||||||
|
if(Short.TYPE.equals(pt)) {
|
||||||
|
return toPrimitive((Short[]) array);
|
||||||
|
}
|
||||||
|
if(Double.TYPE.equals(pt)) {
|
||||||
|
return toPrimitive((Double[]) array);
|
||||||
|
}
|
||||||
|
if(Float.TYPE.equals(pt)) {
|
||||||
|
return toPrimitive((Float[]) array);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
// Boolean array converters
|
// Boolean array converters
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -114,6 +114,10 @@ public class ConstructorUtils {
|
||||||
throw new NoSuchMethodException(
|
throw new NoSuchMethodException(
|
||||||
"No such accessible constructor on object: " + cls.getName());
|
"No such accessible constructor on object: " + cls.getName());
|
||||||
}
|
}
|
||||||
|
if (ctor.isVarArgs()) {
|
||||||
|
Class<?>[] methodParameterTypes = ctor.getParameterTypes();
|
||||||
|
args = MethodUtils.getVarArgs(args, methodParameterTypes);
|
||||||
|
}
|
||||||
return ctor.newInstance(args);
|
return ctor.newInstance(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,14 +262,12 @@ public class ConstructorUtils {
|
||||||
// return best match:
|
// return best match:
|
||||||
for (Constructor<?> ctor : ctors) {
|
for (Constructor<?> ctor : ctors) {
|
||||||
// compare parameters
|
// compare parameters
|
||||||
if (ClassUtils.isAssignable(parameterTypes, ctor.getParameterTypes(), true)) {
|
if (MemberUtils.isMatchingConstructor(ctor, parameterTypes)) {
|
||||||
// get accessible version of constructor
|
// get accessible version of constructor
|
||||||
ctor = getAccessibleConstructor(ctor);
|
ctor = getAccessibleConstructor(ctor);
|
||||||
if (ctor != null) {
|
if (ctor != null) {
|
||||||
MemberUtils.setAccessibleWorkaround(ctor);
|
MemberUtils.setAccessibleWorkaround(ctor);
|
||||||
if (result == null
|
if (result == null || MemberUtils.compareConstructorFit(ctor, result, parameterTypes) < 0) {
|
||||||
|| MemberUtils.compareParameterTypes(ctor.getParameterTypes(), result
|
|
||||||
.getParameterTypes(), parameterTypes) < 0) {
|
|
||||||
// temporary variable for annotation, see comment above (1)
|
// temporary variable for annotation, see comment above (1)
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final
|
final
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
package org.apache.commons.lang3.reflect;
|
package org.apache.commons.lang3.reflect;
|
||||||
|
|
||||||
import java.lang.reflect.AccessibleObject;
|
import java.lang.reflect.AccessibleObject;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ClassUtils;
|
import org.apache.commons.lang3.ClassUtils;
|
||||||
|
@ -85,18 +87,52 @@ abstract class MemberUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares the relative fitness of two sets of parameter types in terms of
|
* Compares the relative fitness of two Constructors in terms of how well they
|
||||||
* matching a third set of runtime parameter types, such that a list ordered
|
* match a set of runtime parameter types, such that a list ordered
|
||||||
* by the results of the comparison would return the best match first
|
* by the results of the comparison would return the best match first
|
||||||
* (least).
|
* (least).
|
||||||
*
|
*
|
||||||
* @param left the "left" parameter set
|
* @param left the "left" Constructor
|
||||||
* @param right the "right" parameter set
|
* @param right the "right" Constructor
|
||||||
|
* @param actual the runtime parameter types to match against
|
||||||
|
* {@code left}/{@code right}
|
||||||
|
* @return int consistent with {@code compare} semantics
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
static int compareConstructorFit(final Constructor<?> left, final Constructor<?> right, final Class<?>[] actual) {
|
||||||
|
return compareParameterTypes(Executable.of(left), Executable.of(right), actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the relative fitness of two Methods in terms of how well they
|
||||||
|
* match a set of runtime parameter types, such that a list ordered
|
||||||
|
* by the results of the comparison would return the best match first
|
||||||
|
* (least).
|
||||||
|
*
|
||||||
|
* @param left the "left" Method
|
||||||
|
* @param right the "right" Method
|
||||||
|
* @param actual the runtime parameter types to match against
|
||||||
|
* {@code left}/{@code right}
|
||||||
|
* @return int consistent with {@code compare} semantics
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
static int compareMethodFit(final Method left, final Method right, final Class<?>[] actual) {
|
||||||
|
return compareParameterTypes(Executable.of(left), Executable.of(right), actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the relative fitness of two Executables in terms of how well they
|
||||||
|
* match a set of runtime parameter types, such that a list ordered
|
||||||
|
* by the results of the comparison would return the best match first
|
||||||
|
* (least).
|
||||||
|
*
|
||||||
|
* @param left the "left" Executable
|
||||||
|
* @param right the "right" Executable
|
||||||
* @param actual the runtime parameter types to match against
|
* @param actual the runtime parameter types to match against
|
||||||
* {@code left}/{@code right}
|
* {@code left}/{@code right}
|
||||||
* @return int consistent with {@code compare} semantics
|
* @return int consistent with {@code compare} semantics
|
||||||
*/
|
*/
|
||||||
static int compareParameterTypes(final Class<?>[] left, final Class<?>[] right, final Class<?>[] actual) {
|
private static int compareParameterTypes(final Executable left, final Executable right, final Class<?>[] actual) {
|
||||||
final float leftCost = getTotalTransformationCost(actual, left);
|
final float leftCost = getTotalTransformationCost(actual, left);
|
||||||
final float rightCost = getTotalTransformationCost(actual, right);
|
final float rightCost = getTotalTransformationCost(actual, right);
|
||||||
return leftCost < rightCost ? -1 : rightCost < leftCost ? 1 : 0;
|
return leftCost < rightCost ? -1 : rightCost < leftCost ? 1 : 0;
|
||||||
|
@ -107,15 +143,44 @@ abstract class MemberUtils {
|
||||||
* source argument list.
|
* source argument list.
|
||||||
* @param srcArgs The source arguments
|
* @param srcArgs The source arguments
|
||||||
* @param destArgs The destination arguments
|
* @param destArgs The destination arguments
|
||||||
|
* @param isVarArgs True if the destination arguments are for a varags methods
|
||||||
* @return The total transformation cost
|
* @return The total transformation cost
|
||||||
*/
|
*/
|
||||||
private static float getTotalTransformationCost(final Class<?>[] srcArgs, final Class<?>[] destArgs) {
|
private static float getTotalTransformationCost(final Class<?>[] srcArgs, final Executable executable) {
|
||||||
|
final Class<?>[] destArgs = executable.getParameterTypes();
|
||||||
|
final boolean isVarArgs = executable.isVarArgs();
|
||||||
|
|
||||||
|
// "source" and "destination" are the actual and declared args respectively.
|
||||||
float totalCost = 0.0f;
|
float totalCost = 0.0f;
|
||||||
for (int i = 0; i < srcArgs.length; i++) {
|
final long normalArgsLen = isVarArgs ? destArgs.length-1 : destArgs.length;
|
||||||
Class<?> srcClass, destClass;
|
if (srcArgs.length < normalArgsLen)
|
||||||
srcClass = srcArgs[i];
|
return Float.MAX_VALUE;
|
||||||
destClass = destArgs[i];
|
for (int i = 0; i < normalArgsLen; i++) {
|
||||||
totalCost += getObjectTransformationCost(srcClass, destClass);
|
totalCost += getObjectTransformationCost(srcArgs[i], destArgs[i]);
|
||||||
|
}
|
||||||
|
if (isVarArgs) {
|
||||||
|
// When isVarArgs is true, srcArgs and dstArgs may differ in length.
|
||||||
|
// There are two special cases to consider:
|
||||||
|
final boolean noVarArgsPassed = srcArgs.length < destArgs.length;
|
||||||
|
final boolean explicitArrayForVarags = (srcArgs.length == destArgs.length) && srcArgs[srcArgs.length-1].isArray();
|
||||||
|
|
||||||
|
final float varArgsCost = 0.001f;
|
||||||
|
Class<?> destClass = destArgs[destArgs.length-1].getComponentType();
|
||||||
|
if (noVarArgsPassed) {
|
||||||
|
// When no varargs passed, the best match is the most generic matching type, not the most specific.
|
||||||
|
totalCost += getObjectTransformationCost(destClass, Object.class) + varArgsCost;
|
||||||
|
}
|
||||||
|
else if (explicitArrayForVarags) {
|
||||||
|
Class<?> sourceClass = srcArgs[srcArgs.length-1].getComponentType();
|
||||||
|
totalCost += getObjectTransformationCost(sourceClass, destClass) + varArgsCost;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// This is typical varargs case.
|
||||||
|
for (int i = destArgs.length-1; i < srcArgs.length; i++) {
|
||||||
|
Class<?> srcClass = srcArgs[i];
|
||||||
|
totalCost += getObjectTransformationCost(srcClass, destClass) + varArgsCost;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return totalCost;
|
return totalCost;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +212,7 @@ abstract class MemberUtils {
|
||||||
srcClass = srcClass.getSuperclass();
|
srcClass = srcClass.getSuperclass();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If the destination class is null, we've travelled all the way up to
|
* If the destination class is null, we've traveled all the way up to
|
||||||
* an Object match. We'll penalize this by adding 1.5 to the cost.
|
* an Object match. We'll penalize this by adding 1.5 to the cost.
|
||||||
*/
|
*/
|
||||||
if (srcClass == null) {
|
if (srcClass == null) {
|
||||||
|
@ -182,4 +247,58 @@ abstract class MemberUtils {
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isMatchingMethod(Method method, Class<?>[] parameterTypes) {
|
||||||
|
return MemberUtils.isMatchingExecutable(Executable.of(method), parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isMatchingConstructor(Constructor<?> method, Class<?>[] parameterTypes) {
|
||||||
|
return MemberUtils.isMatchingExecutable(Executable.of(method), parameterTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMatchingExecutable(Executable method, Class<?>[] parameterTypes) {
|
||||||
|
final Class<?>[] methodParameterTypes = method.getParameterTypes();
|
||||||
|
if (method.isVarArgs()) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < methodParameterTypes.length - 1 && i < parameterTypes.length; i++) {
|
||||||
|
if (!ClassUtils.isAssignable(parameterTypes[i], methodParameterTypes[i], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Class<?> varArgParameterType = methodParameterTypes[methodParameterTypes.length - 1].getComponentType();
|
||||||
|
for (; i < parameterTypes.length; i++) {
|
||||||
|
if (!ClassUtils.isAssignable(parameterTypes[i], varArgParameterType, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ClassUtils.isAssignable(parameterTypes, methodParameterTypes, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p> A class providing a subset of the API of java.lang.reflect.Executable in Java 1.8,
|
||||||
|
* providing a common representation for function signatures for Constructors and Methods.</p>
|
||||||
|
*/
|
||||||
|
private static final class Executable {
|
||||||
|
private final Class<?>[] parameterTypes;
|
||||||
|
private final boolean isVarArgs;
|
||||||
|
|
||||||
|
private static Executable of(Method method) { return new Executable(method); }
|
||||||
|
private static Executable of(Constructor<?> constructor) { return new Executable(constructor); }
|
||||||
|
|
||||||
|
private Executable(Method method) {
|
||||||
|
parameterTypes = method.getParameterTypes();
|
||||||
|
isVarArgs = method.isVarArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Executable(Constructor<?> constructor) {
|
||||||
|
parameterTypes = constructor.getParameterTypes();
|
||||||
|
isVarArgs = constructor.isVarArgs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?>[] getParameterTypes() { return parameterTypes; }
|
||||||
|
|
||||||
|
public boolean isVarArgs() { return isVarArgs; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,14 @@
|
||||||
package org.apache.commons.lang3.reflect;
|
package org.apache.commons.lang3.reflect;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
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;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.TypeVariable;
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -155,6 +156,7 @@ public class MethodUtils {
|
||||||
+ methodName + "() on object: "
|
+ methodName + "() on object: "
|
||||||
+ object.getClass().getName());
|
+ object.getClass().getName());
|
||||||
}
|
}
|
||||||
|
args = toVarArgs(method, args);
|
||||||
return method.invoke(object, args);
|
return method.invoke(object, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,9 +343,61 @@ public class MethodUtils {
|
||||||
throw new NoSuchMethodException("No such accessible method: "
|
throw new NoSuchMethodException("No such accessible method: "
|
||||||
+ methodName + "() on class: " + cls.getName());
|
+ methodName + "() on class: " + cls.getName());
|
||||||
}
|
}
|
||||||
|
args = toVarArgs(method, args);
|
||||||
return method.invoke(null, args);
|
return method.invoke(null, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Object[] toVarArgs(Method method, Object[] args) {
|
||||||
|
if (method.isVarArgs()) {
|
||||||
|
Class<?>[] methodParameterTypes = method.getParameterTypes();
|
||||||
|
args = getVarArgs(args, methodParameterTypes);
|
||||||
|
}
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Given an arguments array passed to a varargs method, return an array of arguments in the canonical form,
|
||||||
|
* i.e. an array with the declared number of parameters, and whose last parameter is an array of the varargs type.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param args the array of arguments passed to the varags method
|
||||||
|
* @param methodParameterTypes the declared array of method parameter types
|
||||||
|
* @return an array of the variadic arguments passed to the method
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
static Object[] getVarArgs(Object[] args, Class<?>[] methodParameterTypes) {
|
||||||
|
if (args.length == methodParameterTypes.length
|
||||||
|
&& args[args.length - 1].getClass().equals(methodParameterTypes[methodParameterTypes.length - 1])) {
|
||||||
|
// The args array is already in the canonical form for the method.
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct a new array matching the method's declared parameter types.
|
||||||
|
Object[] newArgs = new Object[methodParameterTypes.length];
|
||||||
|
|
||||||
|
// Copy the normal (non-varargs) parameters
|
||||||
|
System.arraycopy(args, 0, newArgs, 0, methodParameterTypes.length - 1);
|
||||||
|
|
||||||
|
// Construct a new array for the variadic parameters
|
||||||
|
Class<?> varArgComponentType = methodParameterTypes[methodParameterTypes.length - 1].getComponentType();
|
||||||
|
int varArgLength = args.length - methodParameterTypes.length + 1;
|
||||||
|
|
||||||
|
Object varArgsArray = Array.newInstance(ClassUtils.primitiveToWrapper(varArgComponentType), varArgLength);
|
||||||
|
// Copy the variadic arguments into the varargs array.
|
||||||
|
System.arraycopy(args, methodParameterTypes.length - 1, varArgsArray, 0, varArgLength);
|
||||||
|
|
||||||
|
if(varArgComponentType.isPrimitive()) {
|
||||||
|
// unbox from wrapper type to primitive type
|
||||||
|
varArgsArray = ArrayUtils.toPrimitive(varArgsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the varargs array in the last position of the array to return
|
||||||
|
newArgs[methodParameterTypes.length - 1] = varArgsArray;
|
||||||
|
|
||||||
|
// Return the canonical varargs array.
|
||||||
|
return newArgs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Invokes a {@code 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>
|
||||||
|
@ -533,12 +587,13 @@ public class MethodUtils {
|
||||||
final Method[] methods = cls.getMethods();
|
final Method[] methods = cls.getMethods();
|
||||||
for (final Method method : methods) {
|
for (final Method method : methods) {
|
||||||
// compare name and parameters
|
// compare name and parameters
|
||||||
if (method.getName().equals(methodName) && ClassUtils.isAssignable(parameterTypes, method.getParameterTypes(), true)) {
|
if (method.getName().equals(methodName) &&
|
||||||
|
MemberUtils.isMatchingMethod(method, parameterTypes)) {
|
||||||
// get accessible version of method
|
// get accessible version of method
|
||||||
final Method accessibleMethod = getAccessibleMethod(method);
|
final Method accessibleMethod = getAccessibleMethod(method);
|
||||||
if (accessibleMethod != null && (bestMatch == null || MemberUtils.compareParameterTypes(
|
if (accessibleMethod != null && (bestMatch == null || MemberUtils.compareMethodFit(
|
||||||
accessibleMethod.getParameterTypes(),
|
accessibleMethod,
|
||||||
bestMatch.getParameterTypes(),
|
bestMatch,
|
||||||
parameterTypes) < 0)) {
|
parameterTypes) < 0)) {
|
||||||
bestMatch = accessibleMethod;
|
bestMatch = accessibleMethod;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,15 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.lang3;
|
package org.apache.commons.lang3;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNotSame;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
@ -25,6 +33,7 @@ import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4406,4 +4415,14 @@ public class ArrayUtilsTest {
|
||||||
assertFalse(ArrayUtils.isSorted(array));
|
assertFalse(ArrayUtils.isSorted(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatePrimitiveArray() {
|
||||||
|
Assert.assertNull(ArrayUtils.toPrimitive((Object[])null));
|
||||||
|
Assert.assertArrayEquals(new int[]{}, (int[]) ArrayUtils.toPrimitive(new Integer[]{}));
|
||||||
|
Assert.assertArrayEquals(new short[]{2}, (short[]) ArrayUtils.toPrimitive(new Short[]{2}));
|
||||||
|
Assert.assertArrayEquals(new long[]{2, 3}, (long[]) ArrayUtils.toPrimitive(new Long[]{2L, 3L}));
|
||||||
|
Assert.assertArrayEquals(new float[]{3.14f}, (float[]) ArrayUtils.toPrimitive(new Float[]{3.14f}), 0.1f);
|
||||||
|
Assert.assertArrayEquals(new double[]{2.718}, (double[]) ArrayUtils.toPrimitive(new Double[]{2.718}), 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.commons.lang3.reflect;
|
package org.apache.commons.lang3.reflect;
|
||||||
|
|
||||||
import org.junit.Test;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.Before;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -29,6 +30,9 @@ import java.util.Map;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests ConstructorUtils
|
* Unit tests ConstructorUtils
|
||||||
|
@ -36,35 +40,65 @@ import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
public class ConstructorUtilsTest {
|
public class ConstructorUtilsTest {
|
||||||
public static class TestBean {
|
public static class TestBean {
|
||||||
private final String toString;
|
private final String toString;
|
||||||
|
final String[] varArgs;
|
||||||
|
|
||||||
public TestBean() {
|
public TestBean() {
|
||||||
toString = "()";
|
toString = "()";
|
||||||
|
varArgs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestBean(final int i) {
|
public TestBean(final int i) {
|
||||||
toString = "(int)";
|
toString = "(int)";
|
||||||
|
varArgs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestBean(final Integer i) {
|
public TestBean(final Integer i) {
|
||||||
toString = "(Integer)";
|
toString = "(Integer)";
|
||||||
|
varArgs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestBean(final double d) {
|
public TestBean(final double d) {
|
||||||
toString = "(double)";
|
toString = "(double)";
|
||||||
|
varArgs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestBean(final String s) {
|
public TestBean(final String s) {
|
||||||
toString = "(String)";
|
toString = "(String)";
|
||||||
|
varArgs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestBean(final Object o) {
|
public TestBean(final Object o) {
|
||||||
toString = "(Object)";
|
toString = "(Object)";
|
||||||
|
varArgs = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(final String... s) {
|
||||||
|
toString = "(String...)";
|
||||||
|
varArgs = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(final Integer i, String... s) {
|
||||||
|
toString = "(Integer, String...)";
|
||||||
|
varArgs = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestBean(final Integer first, int... args) {
|
||||||
|
toString = "(Integer, String...)";
|
||||||
|
varArgs = new String[args.length];
|
||||||
|
for(int i = 0; i< args.length; ++i) {
|
||||||
|
varArgs[i] = Integer.toString(args[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toString;
|
return toString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verify(final String str, final String[] args) {
|
||||||
|
assertEquals(str, toString);
|
||||||
|
assertEquals(args, varArgs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PrivateClass {
|
private static class PrivateClass {
|
||||||
|
@ -117,6 +151,12 @@ public class ConstructorUtilsTest {
|
||||||
TestBean.class, NumberUtils.LONG_ONE).toString());
|
TestBean.class, NumberUtils.LONG_ONE).toString());
|
||||||
assertEquals("(double)", ConstructorUtils.invokeConstructor(
|
assertEquals("(double)", ConstructorUtils.invokeConstructor(
|
||||||
TestBean.class, NumberUtils.DOUBLE_ONE).toString());
|
TestBean.class, NumberUtils.DOUBLE_ONE).toString());
|
||||||
|
ConstructorUtils.invokeConstructor(TestBean.class, NumberUtils.INTEGER_ONE)
|
||||||
|
.verify("(Integer)", null);
|
||||||
|
ConstructorUtils.invokeConstructor(TestBean.class, "a", "b")
|
||||||
|
.verify("(String...)", new String[]{"a", "b"});
|
||||||
|
ConstructorUtils.invokeConstructor(TestBean.class, NumberUtils.INTEGER_ONE, "a", "b")
|
||||||
|
.verify("(Integer, String...)", new String[]{"a", "b"});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -242,4 +282,12 @@ public class ConstructorUtilsTest {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVarArgsUnboxing() throws Exception {
|
||||||
|
TestBean testBean = ConstructorUtils.invokeConstructor(
|
||||||
|
TestBean.class, Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3));
|
||||||
|
|
||||||
|
Assert.assertArrayEquals(new String[]{"2", "3"}, testBean.varArgs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,16 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.ClassUtils.Interfaces;
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
import org.apache.commons.lang3.mutable.Mutable;
|
import org.apache.commons.lang3.mutable.Mutable;
|
||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
import org.apache.commons.lang3.ClassUtils.Interfaces;
|
|
||||||
import org.apache.commons.lang3.reflect.testbed.Annotated;
|
import org.apache.commons.lang3.reflect.testbed.Annotated;
|
||||||
import org.apache.commons.lang3.reflect.testbed.GenericConsumer;
|
import org.apache.commons.lang3.reflect.testbed.GenericConsumer;
|
||||||
import org.apache.commons.lang3.reflect.testbed.GenericParent;
|
import org.apache.commons.lang3.reflect.testbed.GenericParent;
|
||||||
import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
|
import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -88,6 +90,14 @@ public class MethodUtilsTest {
|
||||||
return "bar(Object)";
|
return "bar(Object)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String bar(final String... s) {
|
||||||
|
return "bar(String...)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String bar(final Integer i, final String... s) {
|
||||||
|
return "bar(int, String...)";
|
||||||
|
}
|
||||||
|
|
||||||
public static void oneParameterStatic(final String s) {
|
public static void oneParameterStatic(final String s) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
@ -121,9 +131,77 @@ public class MethodUtilsTest {
|
||||||
return "foo(Object)";
|
return "foo(Object)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String foo(final String... s) {
|
||||||
|
return "foo(String...)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String foo(final Integer i, final String... s) {
|
||||||
|
return "foo(int, String...)";
|
||||||
|
}
|
||||||
|
|
||||||
public void oneParameter(final String s) {
|
public void oneParameter(final String s) {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String foo(final Object... s) {
|
||||||
|
return "foo(Object...)";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] unboxing(int... values) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is overloaded for the wrapper class for every primitive type, plus the common supertypes
|
||||||
|
// Number and Object. This is an acid test since it easily leads to ambiguous methods.
|
||||||
|
public static String varOverload(Byte... args) { return "Byte..."; }
|
||||||
|
public static String varOverload(Character... args) { return "Character..."; }
|
||||||
|
public static String varOverload(Short... args) { return "Short..."; }
|
||||||
|
public static String varOverload(Boolean... args) { return "Boolean..."; }
|
||||||
|
public static String varOverload(Float... args) { return "Float..."; }
|
||||||
|
public static String varOverload(Double... args) { return "Double..."; }
|
||||||
|
public static String varOverload(Integer... args) { return "Integer..."; }
|
||||||
|
public static String varOverload(Long... args) { return "Long..."; }
|
||||||
|
public static String varOverload(Number... args) { return "Number..."; }
|
||||||
|
public static String varOverload(Object... args) { return "Object..."; }
|
||||||
|
public static String varOverload(String... args) { return "String..."; }
|
||||||
|
|
||||||
|
// This method is overloaded for the wrapper class for every numeric primitive type, plus the common
|
||||||
|
// supertype Number
|
||||||
|
public static String numOverload(Byte... args) { return "Byte..."; }
|
||||||
|
public static String numOverload(Short... args) { return "Short..."; }
|
||||||
|
public static String numOverload(Float... args) { return "Float..."; }
|
||||||
|
public static String numOverload(Double... args) { return "Double..."; }
|
||||||
|
public static String numOverload(Integer... args) { return "Integer..."; }
|
||||||
|
public static String numOverload(Long... args) { return "Long..."; }
|
||||||
|
public static String numOverload(Number... args) { return "Number..."; }
|
||||||
|
|
||||||
|
// These varOverloadEcho and varOverloadEchoStatic methods are designed to verify that
|
||||||
|
// not only is the correct overloaded variant invoked, but that the varags arguments
|
||||||
|
// are also delivered correctly to the method.
|
||||||
|
public ImmutablePair<String, Object[]> varOverloadEcho(String... args) {
|
||||||
|
return new ImmutablePair<String, Object[]>("String...", args);
|
||||||
|
}
|
||||||
|
public ImmutablePair<String, Object[]> varOverloadEcho(Number... args) {
|
||||||
|
return new ImmutablePair<String, Object[]>("Number...", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ImmutablePair<String, Object[]> varOverloadEchoStatic(String... args) {
|
||||||
|
return new ImmutablePair<String, Object[]>("String...", args);
|
||||||
|
}
|
||||||
|
public static ImmutablePair<String, Object[]> varOverloadEchoStatic(Number... args) {
|
||||||
|
return new ImmutablePair<String, Object[]>("Number...", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify(ImmutablePair<String, Object[]> a, ImmutablePair<String, Object[]> b) {
|
||||||
|
assertEquals(a.getLeft(), b.getLeft());
|
||||||
|
assertArrayEquals(a.getRight(), b.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify(ImmutablePair<String, Object[]> a, Object _b) {
|
||||||
|
final ImmutablePair<String, Object[]> b = (ImmutablePair<String, Object[]>) _b;
|
||||||
|
verify(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestMutable implements Mutable<Object> {
|
private static class TestMutable implements Mutable<Object> {
|
||||||
|
@ -151,6 +229,81 @@ public class MethodUtilsTest {
|
||||||
assertNotNull(MethodUtils.class.newInstance());
|
assertNotNull(MethodUtils.class.newInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyJavaVarargsOverloadingResolution() throws Exception {
|
||||||
|
// This code is not a test of MethodUtils.
|
||||||
|
// Rather it makes explicit the behavior of the Java specification for
|
||||||
|
// various cases of overload resolution.
|
||||||
|
assertEquals("Byte...", TestBean.varOverload((byte) 1, (byte) 2));
|
||||||
|
assertEquals("Short...", TestBean.varOverload((short) 1, (short) 2));
|
||||||
|
assertEquals("Integer...", TestBean.varOverload(1, 2));
|
||||||
|
assertEquals("Long...", TestBean.varOverload(1L, 2L));
|
||||||
|
assertEquals("Float...", TestBean.varOverload(1f, 2f));
|
||||||
|
assertEquals("Double...", TestBean.varOverload(1d, 2d));
|
||||||
|
assertEquals("Character...", TestBean.varOverload('a', 'b'));
|
||||||
|
assertEquals("String...", TestBean.varOverload("a", "b"));
|
||||||
|
assertEquals("Boolean...", TestBean.varOverload(true, false));
|
||||||
|
|
||||||
|
assertEquals("Object...", TestBean.varOverload(1, "s"));
|
||||||
|
assertEquals("Object...", TestBean.varOverload(1, true));
|
||||||
|
assertEquals("Object...", TestBean.varOverload(1.1, true));
|
||||||
|
assertEquals("Object...", TestBean.varOverload('c', true));
|
||||||
|
assertEquals("Number...", TestBean.varOverload(1, 1.1));
|
||||||
|
assertEquals("Number...", TestBean.varOverload(1, 1L));
|
||||||
|
assertEquals("Number...", TestBean.varOverload(1d, 1f));
|
||||||
|
assertEquals("Number...", TestBean.varOverload((short) 1, (byte) 1));
|
||||||
|
assertEquals("Object...", TestBean.varOverload(1, 'c'));
|
||||||
|
assertEquals("Object...", TestBean.varOverload('c', "s"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvokeJavaVarargsOverloadingResolution() throws Exception {
|
||||||
|
assertEquals("Byte...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", (byte) 1, (byte) 2));
|
||||||
|
assertEquals("Short...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", (short) 1, (short) 2));
|
||||||
|
assertEquals("Integer...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, 2));
|
||||||
|
assertEquals("Long...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1L, 2L));
|
||||||
|
assertEquals("Float...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1f, 2f));
|
||||||
|
assertEquals("Double...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1d, 2d));
|
||||||
|
assertEquals("Character...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 'a', 'b'));
|
||||||
|
assertEquals("String...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", "a", "b"));
|
||||||
|
assertEquals("Boolean...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", true, false));
|
||||||
|
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, "s"));
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, true));
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1.1, true));
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 'c', true));
|
||||||
|
assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, 1.1));
|
||||||
|
assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, 1L));
|
||||||
|
assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1d, 1f));
|
||||||
|
assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", (short) 1, (byte) 1));
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 1, 'c'));
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class,
|
||||||
|
"varOverload", 'c', "s"));
|
||||||
|
|
||||||
|
assertEquals("Object...", MethodUtils.invokeStaticMethod(TestBean.class, "varOverload",
|
||||||
|
(Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
assertEquals("Number...", MethodUtils.invokeStaticMethod(TestBean.class, "numOverload",
|
||||||
|
(Object[]) ArrayUtils.EMPTY_CLASS_ARRAY));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvokeMethod() throws Exception {
|
public void testInvokeMethod() throws Exception {
|
||||||
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
assertEquals("foo()", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
@ -174,6 +327,21 @@ public class MethodUtilsTest {
|
||||||
NumberUtils.LONG_ONE));
|
NumberUtils.LONG_ONE));
|
||||||
assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
|
assertEquals("foo(double)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
NumberUtils.DOUBLE_ONE));
|
NumberUtils.DOUBLE_ONE));
|
||||||
|
assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
"a", "b", "c"));
|
||||||
|
assertEquals("foo(String...)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
"a", "b", "c"));
|
||||||
|
assertEquals("foo(int, String...)", MethodUtils.invokeMethod(testBean, "foo",
|
||||||
|
5, "a", "b", "c"));
|
||||||
|
|
||||||
|
TestBean.verify(new ImmutablePair("String...", new String[]{"x", "y"}),
|
||||||
|
MethodUtils.invokeMethod(testBean, "varOverloadEcho", "x", "y"));
|
||||||
|
TestBean.verify(new ImmutablePair("Number...", new Number[]{17, 23, 42}),
|
||||||
|
MethodUtils.invokeMethod(testBean, "varOverloadEcho", 17, 23, 42));
|
||||||
|
TestBean.verify(new ImmutablePair("String...", new String[]{"x", "y"}),
|
||||||
|
MethodUtils.invokeMethod(testBean, "varOverloadEcho", new String[]{"x", "y"}));
|
||||||
|
TestBean.verify(new ImmutablePair("Number...", new Number[]{17, 23, 42}),
|
||||||
|
MethodUtils.invokeMethod(testBean, "varOverloadEcho", new Number[]{17, 23, 42}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -236,6 +404,19 @@ public class MethodUtilsTest {
|
||||||
TestBean.class, "bar", NumberUtils.LONG_ONE));
|
TestBean.class, "bar", NumberUtils.LONG_ONE));
|
||||||
assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
|
assertEquals("bar(double)", MethodUtils.invokeStaticMethod(
|
||||||
TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
|
TestBean.class, "bar", NumberUtils.DOUBLE_ONE));
|
||||||
|
assertEquals("bar(String...)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", "a", "b"));
|
||||||
|
assertEquals("bar(int, String...)", MethodUtils.invokeStaticMethod(
|
||||||
|
TestBean.class, "bar", NumberUtils.INTEGER_ONE, "a", "b"));
|
||||||
|
|
||||||
|
TestBean.verify(new ImmutablePair("String...", new String[]{"x", "y"}),
|
||||||
|
MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", "x", "y"));
|
||||||
|
TestBean.verify(new ImmutablePair("Number...", new Number[]{17, 23, 42}),
|
||||||
|
MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", 17, 23, 42));
|
||||||
|
TestBean.verify(new ImmutablePair("String...", new String[]{"x", "y"}),
|
||||||
|
MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", new String[]{"x", "y"}));
|
||||||
|
TestBean.verify(new ImmutablePair("Number...", new Number[]{17, 23, 42}),
|
||||||
|
MethodUtils.invokeStaticMethod(TestBean.class, "varOverloadEchoStatic", new Number[]{17, 23, 42}));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MethodUtils.invokeStaticMethod(TestBean.class, "does_not_exist");
|
MethodUtils.invokeStaticMethod(TestBean.class, "does_not_exist");
|
||||||
|
@ -375,6 +556,10 @@ public class MethodUtilsTest {
|
||||||
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
||||||
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
singletonArray(Double.TYPE), singletonArray(Double.TYPE));
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
new Class[] {String.class, String.class}, new Class[] {String[].class});
|
||||||
|
expectMatchingAccessibleMethodParameterTypes(TestBean.class, "foo",
|
||||||
|
new Class[] {Integer.TYPE, String.class, String.class}, new Class[] {Integer.class, String[].class});
|
||||||
expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
|
expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
|
||||||
singletonArray(ParentObject.class), singletonArray(ParentObject.class));
|
singletonArray(ParentObject.class), singletonArray(ParentObject.class));
|
||||||
expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
|
expectMatchingAccessibleMethodParameterTypes(InheritanceBean.class, "testOne",
|
||||||
|
@ -490,6 +675,8 @@ public class MethodUtilsTest {
|
||||||
final String methodName, final Class<?>[] requestTypes, final Class<?>[] actualTypes) {
|
final String methodName, final Class<?>[] requestTypes, final Class<?>[] actualTypes) {
|
||||||
final Method m = MethodUtils.getMatchingAccessibleMethod(cls, methodName,
|
final Method m = MethodUtils.getMatchingAccessibleMethod(cls, methodName,
|
||||||
requestTypes);
|
requestTypes);
|
||||||
|
assertNotNull("could not find any matches for " + methodName
|
||||||
|
+ " (" + (requestTypes == null ? null : toString(requestTypes)) + ")", m);
|
||||||
assertTrue(toString(m.getParameterTypes()) + " not equals "
|
assertTrue(toString(m.getParameterTypes()) + " not equals "
|
||||||
+ toString(actualTypes), Arrays.equals(actualTypes, m
|
+ toString(actualTypes), Arrays.equals(actualTypes, m
|
||||||
.getParameterTypes()));
|
.getParameterTypes()));
|
||||||
|
@ -533,4 +720,11 @@ public class MethodUtilsTest {
|
||||||
this.parameterTypes = parameterTypes;
|
this.parameterTypes = parameterTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVarArgsUnboxing() throws Exception {
|
||||||
|
TestBean testBean = new TestBean();
|
||||||
|
int[] actual = (int[])MethodUtils.invokeMethod(testBean, "unboxing", Integer.valueOf(1), Integer.valueOf(2));
|
||||||
|
Assert.assertArrayEquals(new int[]{1, 2}, actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue