Moved isAssignmentCompatable method from MethodUtils into ReflectionUtils and renamed it. Enhanced existing isCompatible so that widening of primitives is allowed. Created test case for moved method.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@137139 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b991b3f973
commit
0cc87fe88d
|
@ -82,7 +82,7 @@ import org.apache.commons.lang.StringUtils;
|
|||
* @author Gregor Raýman
|
||||
* @author Jan Sorensen
|
||||
* @author Robert Burrell Donkin
|
||||
* @version $Id: MethodUtils.java,v 1.4 2002/11/18 23:00:26 rdonkin Exp $
|
||||
* @version $Id: MethodUtils.java,v 1.5 2002/11/20 21:45:47 rdonkin Exp $
|
||||
*/
|
||||
public class MethodUtils {
|
||||
|
||||
|
@ -570,7 +570,7 @@ public class MethodUtils {
|
|||
log("Param=" + parameterTypes[n].getName());
|
||||
log("Method=" + methodsParams[n].getName());
|
||||
}
|
||||
if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
|
||||
if (!ReflectionUtils.isCompatable(parameterTypes[n], methodsParams[n])) {
|
||||
if (debug) {
|
||||
log(methodsParams[n] + " is not assignable from "
|
||||
+ parameterTypes[n]);
|
||||
|
@ -613,56 +613,7 @@ public class MethodUtils {
|
|||
// didn't find a match
|
||||
log("No match found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Determine whether a type can be used as a parameter in a method invocation.
|
||||
* This method handles primitive conversions correctly.</p>
|
||||
*
|
||||
* <p>In order words, it will match a <code>Boolean</code> to a <code>boolean</code>,
|
||||
* a <code>Long</code> to a <code>long</code>,
|
||||
* a <code>Float</code> to a <code>float</code>,
|
||||
* a <code>Integer</code> to a <code>int</code>,
|
||||
* and a <code>Double</code> to a <code>double</code>.
|
||||
* Now logic widening matches are allowed.
|
||||
* For example, a <code>Long</code> will not match a <code>int</code>.
|
||||
*
|
||||
* @param parameterType the type of parameter accepted by the method
|
||||
* @param parameterization the type of parameter being tested
|
||||
*
|
||||
* @return true if the assignement is compatible.
|
||||
*/
|
||||
private static final boolean isAssignmentCompatible(Class parameterType, Class parameterization) {
|
||||
// try plain assignment
|
||||
if (parameterType.isAssignableFrom(parameterization)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parameterType.isPrimitive()) {
|
||||
// does anyone know a better strategy than comparing names?
|
||||
// also, this method does *not* do widening - you must specify exactly
|
||||
// is this the right behaviour?
|
||||
if (boolean.class.equals(parameterType)) {
|
||||
return Boolean.class.equals(parameterization);
|
||||
}
|
||||
if (float.class.equals(parameterType)) {
|
||||
return Float.class.equals(parameterization);
|
||||
}
|
||||
if (long.class.equals(parameterType)) {
|
||||
return Long.class.equals(parameterization);
|
||||
}
|
||||
if (int.class.equals(parameterType)) {
|
||||
return Integer.class.equals(parameterization);
|
||||
}
|
||||
if (double.class.equals(parameterType)) {
|
||||
return Double.class.equals(parameterization);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void log(Object o) {
|
||||
if (debug) {
|
||||
|
|
|
@ -69,7 +69,7 @@ import org.apache.commons.lang.StringUtils;
|
|||
* reflection.
|
||||
*
|
||||
* @author <a href="mailto:scolebourne@apache.org">Stephen Colebourne</a>
|
||||
* @version $Id: ReflectionUtils.java,v 1.2 2002/11/18 23:01:36 rdonkin Exp $
|
||||
* @version $Id: ReflectionUtils.java,v 1.3 2002/11/20 21:45:47 rdonkin Exp $
|
||||
*/
|
||||
public class ReflectionUtils {
|
||||
|
||||
|
@ -197,7 +197,10 @@ public class ReflectionUtils {
|
|||
* Primitive classes are handled correctly .
|
||||
* <p>
|
||||
* In other words, a <code>boolean</code> Class will be converted to
|
||||
* a <code>Boolean</code> Class and so on.
|
||||
* a <code>Boolean</code> Class and so on.</p>
|
||||
*
|
||||
* <p>This method also handles widening for primitives as given in section 5.1.2 of the
|
||||
* <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>.
|
||||
*
|
||||
* @param requestedTypes the class array requested
|
||||
* @param paramTypes the actual class array for the method
|
||||
|
@ -214,13 +217,90 @@ public class ReflectionUtils {
|
|||
paramTypes = ArrayUtils.EMPTY_CLASS_ARRAY;
|
||||
}
|
||||
for (int i = 0; i < requestedTypes.length; i++) {
|
||||
if (ClassUtils.isAssignable(requestedTypes[i], paramTypes[i]) == false) {
|
||||
if (isCompatable(requestedTypes[i], paramTypes[i]) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Determine whether a type can be used as a parameter in a method invocation.
|
||||
* This method handles primitive conversions correctly.</p>
|
||||
*
|
||||
* <p>This method also handles widening for primitives as given in section 5.1.2 of the
|
||||
* <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>.
|
||||
*
|
||||
* @param parameterType the type of parameter accepted by the method
|
||||
* @param requestedType the type of parameter being requested
|
||||
*
|
||||
* @return true if the assignement is compatible.
|
||||
*/
|
||||
public static boolean isCompatable(Class requestedType, Class parameterType) {
|
||||
// try plain assignment
|
||||
if (ClassUtils.isAssignable(requestedType, parameterType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (parameterType.isPrimitive()) {
|
||||
// also, this method does *not* do widening - you must specify exactly
|
||||
// is this the right behaviour?
|
||||
if (boolean.class.equals(parameterType)) {
|
||||
return Boolean.class.equals(requestedType);
|
||||
}
|
||||
|
||||
if (byte.class.equals(parameterType)) {
|
||||
return Byte.class.equals(requestedType);
|
||||
}
|
||||
|
||||
if (short.class.equals(parameterType)) {
|
||||
return (Short.class.equals(requestedType)
|
||||
|| Byte.class.equals(requestedType));
|
||||
}
|
||||
|
||||
if (char.class.equals(parameterType)) {
|
||||
return Character.class.equals(requestedType);
|
||||
}
|
||||
|
||||
if (int.class.equals(parameterType)) {
|
||||
return (Integer.class.equals(requestedType)
|
||||
|| Character.class.equals(requestedType)
|
||||
|| Short.class.equals(requestedType)
|
||||
|| Byte.class.equals(requestedType));
|
||||
}
|
||||
if (long.class.equals(parameterType)) {
|
||||
return (Long.class.equals(requestedType)
|
||||
|| Integer.class.equals(requestedType)
|
||||
|| Character.class.equals(requestedType)
|
||||
|| Short.class.equals(requestedType)
|
||||
|| Byte.class.equals(requestedType));
|
||||
}
|
||||
|
||||
if (float.class.equals(parameterType)) {
|
||||
return (Float.class.equals(requestedType)
|
||||
|| Long.class.equals(requestedType)
|
||||
|| Integer.class.equals(requestedType)
|
||||
|| Character.class.equals(requestedType)
|
||||
|| Short.class.equals(requestedType)
|
||||
|| Byte.class.equals(requestedType));
|
||||
}
|
||||
|
||||
if (double.class.equals(parameterType)) {
|
||||
return (Double.class.equals(requestedType)
|
||||
|| Float.class.equals(requestedType)
|
||||
|| Long.class.equals(requestedType)
|
||||
|| Integer.class.equals(requestedType)
|
||||
|| Character.class.equals(requestedType)
|
||||
|| Short.class.equals(requestedType)
|
||||
|| Byte.class.equals(requestedType));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a primitive class to its matching object class.
|
||||
* Non-primitive classes are unaffected.
|
||||
|
|
|
@ -67,6 +67,15 @@ public class PrimitiveBean {
|
|||
private boolean _boolean;
|
||||
private long _long;
|
||||
private int _int;
|
||||
private short _short;
|
||||
|
||||
public short getShort() {
|
||||
return _short;
|
||||
}
|
||||
|
||||
public void setShort(short _short) {
|
||||
this._short = _short;
|
||||
}
|
||||
|
||||
public float getFloat() {
|
||||
return _float;
|
||||
|
|
|
@ -202,4 +202,87 @@ public class ReflectionUtilsTestCase extends TestCase {
|
|||
assertEquals("Static scope (method) [isPublicScope]", true, ReflectionUtils.isPublicScope(method));
|
||||
assertEquals("Static scope (method) [isStatic]", true, ReflectionUtils.isStatic(method));
|
||||
}
|
||||
|
||||
public void testWidening() throws Exception
|
||||
{
|
||||
// test byte conversions
|
||||
assertEquals("byte -> char", ReflectionUtils.isCompatable(Byte.class, char.class), false);
|
||||
assertEquals("byte -> byte", ReflectionUtils.isCompatable(Byte.class, byte.class), true);
|
||||
assertEquals("byte -> short", ReflectionUtils.isCompatable(Byte.class, short.class), true);
|
||||
assertEquals("byte -> int", ReflectionUtils.isCompatable(Byte.class, int.class), true);
|
||||
assertEquals("byte -> long", ReflectionUtils.isCompatable(Byte.class, long.class), true);
|
||||
assertEquals("byte -> float", ReflectionUtils.isCompatable(Byte.class, float.class), true);
|
||||
assertEquals("byte -> double", ReflectionUtils.isCompatable(Byte.class, double.class), true);
|
||||
assertEquals("byte -> boolean", ReflectionUtils.isCompatable(Byte.class, boolean.class), false);
|
||||
|
||||
// test short conversions
|
||||
assertEquals("short -> char", ReflectionUtils.isCompatable(Short.class, char.class), false);
|
||||
assertEquals("short -> byte", ReflectionUtils.isCompatable(Short.class, byte.class), false);
|
||||
assertEquals("short -> short", ReflectionUtils.isCompatable(Short.class, short.class), true);
|
||||
assertEquals("short -> int", ReflectionUtils.isCompatable(Short.class, int.class), true);
|
||||
assertEquals("short -> long", ReflectionUtils.isCompatable(Short.class, long.class), true);
|
||||
assertEquals("short -> float", ReflectionUtils.isCompatable(Short.class, float.class), true);
|
||||
assertEquals("short -> double", ReflectionUtils.isCompatable(Short.class, double.class), true);
|
||||
assertEquals("short -> boolean", ReflectionUtils.isCompatable(Short.class, boolean.class), false);
|
||||
|
||||
// test char conversions
|
||||
assertEquals("char -> char", ReflectionUtils.isCompatable(Character.class, char.class), true);
|
||||
assertEquals("char -> byte", ReflectionUtils.isCompatable(Character.class, byte.class), false);
|
||||
assertEquals("char -> short", ReflectionUtils.isCompatable(Character.class, short.class), false);
|
||||
assertEquals("char -> int", ReflectionUtils.isCompatable(Character.class, int.class), true);
|
||||
assertEquals("char -> long", ReflectionUtils.isCompatable(Character.class, long.class), true);
|
||||
assertEquals("char -> float", ReflectionUtils.isCompatable(Character.class, float.class), true);
|
||||
assertEquals("char -> double", ReflectionUtils.isCompatable(Character.class, double.class), true);
|
||||
assertEquals("char -> boolean", ReflectionUtils.isCompatable(Character.class, boolean.class), false);
|
||||
|
||||
// test int conversions
|
||||
assertEquals("int -> char", ReflectionUtils.isCompatable(Integer.class, char.class), false);
|
||||
assertEquals("int -> byte", ReflectionUtils.isCompatable(Integer.class, byte.class), false);
|
||||
assertEquals("int -> short", ReflectionUtils.isCompatable(Integer.class, short.class), false);
|
||||
assertEquals("int -> int", ReflectionUtils.isCompatable(Integer.class, int.class), true);
|
||||
assertEquals("int -> long", ReflectionUtils.isCompatable(Integer.class, long.class), true);
|
||||
assertEquals("int -> float", ReflectionUtils.isCompatable(Integer.class, float.class), true);
|
||||
assertEquals("int -> double", ReflectionUtils.isCompatable(Integer.class, double.class), true);
|
||||
assertEquals("int -> boolean", ReflectionUtils.isCompatable(Integer.class, boolean.class), false);
|
||||
|
||||
// test long conversions
|
||||
assertEquals("long -> char", ReflectionUtils.isCompatable(Long.class, char.class), false);
|
||||
assertEquals("long -> byte", ReflectionUtils.isCompatable(Long.class, byte.class), false);
|
||||
assertEquals("long -> short", ReflectionUtils.isCompatable(Long.class, short.class), false);
|
||||
assertEquals("long -> int", ReflectionUtils.isCompatable(Long.class, int.class), false);
|
||||
assertEquals("long -> long", ReflectionUtils.isCompatable(Long.class, long.class), true);
|
||||
assertEquals("long -> float", ReflectionUtils.isCompatable(Long.class, float.class), true);
|
||||
assertEquals("long -> double", ReflectionUtils.isCompatable(Long.class, double.class), true);
|
||||
assertEquals("long -> boolean", ReflectionUtils.isCompatable(Long.class, boolean.class), false);
|
||||
|
||||
// test float conversions
|
||||
assertEquals("float -> char", ReflectionUtils.isCompatable(Float.class, char.class), false);
|
||||
assertEquals("float -> byte", ReflectionUtils.isCompatable(Float.class, byte.class), false);
|
||||
assertEquals("float -> short", ReflectionUtils.isCompatable(Float.class, short.class), false);
|
||||
assertEquals("float -> int", ReflectionUtils.isCompatable(Float.class, int.class), false);
|
||||
assertEquals("float -> long", ReflectionUtils.isCompatable(Float.class, long.class), false);
|
||||
assertEquals("float -> float", ReflectionUtils.isCompatable(Float.class, float.class), true);
|
||||
assertEquals("float -> double", ReflectionUtils.isCompatable(Float.class, double.class), true);
|
||||
assertEquals("float -> boolean", ReflectionUtils.isCompatable(Float.class, boolean.class), false);
|
||||
|
||||
// test float conversions
|
||||
assertEquals("double -> char", ReflectionUtils.isCompatable(Double.class, char.class), false);
|
||||
assertEquals("double -> byte", ReflectionUtils.isCompatable(Double.class, byte.class), false);
|
||||
assertEquals("double -> short", ReflectionUtils.isCompatable(Double.class, short.class), false);
|
||||
assertEquals("double -> int", ReflectionUtils.isCompatable(Double.class, int.class), false);
|
||||
assertEquals("double -> long", ReflectionUtils.isCompatable(Double.class, long.class), false);
|
||||
assertEquals("double -> float", ReflectionUtils.isCompatable(Double.class, float.class), false);
|
||||
assertEquals("double -> double", ReflectionUtils.isCompatable(Double.class, double.class), true);
|
||||
assertEquals("double -> boolean", ReflectionUtils.isCompatable(Double.class, boolean.class), false);
|
||||
|
||||
// test float conversions
|
||||
assertEquals("boolean -> char", ReflectionUtils.isCompatable(Boolean.class, char.class), false);
|
||||
assertEquals("boolean -> byte", ReflectionUtils.isCompatable(Boolean.class, byte.class), false);
|
||||
assertEquals("boolean -> short", ReflectionUtils.isCompatable(Boolean.class, short.class), false);
|
||||
assertEquals("boolean -> int", ReflectionUtils.isCompatable(Boolean.class, int.class), false);
|
||||
assertEquals("boolean -> long", ReflectionUtils.isCompatable(Boolean.class, long.class), false);
|
||||
assertEquals("boolean -> float", ReflectionUtils.isCompatable(Boolean.class, float.class), false);
|
||||
assertEquals("boolean -> double", ReflectionUtils.isCompatable(Boolean.class, double.class), false);
|
||||
assertEquals("boolean -> boolean", ReflectionUtils.isCompatable(Boolean.class, boolean.class), true);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue