You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2008/03/19 05:27:42 UTC
svn commit: r638702 - in /commons/proper/lang/branches/LANG_POST_2_4/src:
java/org/apache/commons/lang/ClassUtils.java
test/org/apache/commons/lang/ClassUtilsTest.java
Author: mbenson
Date: Tue Mar 18 21:27:41 2008
New Revision: 638702
URL: http://svn.apache.org/viewvc?rev=638702&view=rev
Log:
isAssignable with autoboxing
Modified:
commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ClassUtils.java
commons/proper/lang/branches/LANG_POST_2_4/src/test/org/apache/commons/lang/ClassUtilsTest.java
Modified: commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ClassUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ClassUtils.java?rev=638702&r1=638701&r2=638702&view=diff
==============================================================================
--- commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ClassUtils.java (original)
+++ commons/proper/lang/branches/LANG_POST_2_4/src/java/org/apache/commons/lang/ClassUtils.java Tue Mar 18 21:27:41 2008
@@ -393,6 +393,42 @@
* @return <code>true</code> if assignment possible
*/
public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+ return isAssignable(classArray, toClassArray, false);
+ }
+
+ /**
+ * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
+ *
+ * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+ * Class pair in the input arrays. It can be used to check if a set of arguments
+ * (the first parameter) are suitably compatible with a set of method parameter types
+ * (the second parameter).</p>
+ *
+ * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+ * method takes into account widenings of primitive classes and
+ * <code>null</code>s.</p>
+ *
+ * <p>Primitive widenings allow an int to be assigned to a <code>long</code>,
+ * <code>float</code> or <code>double</code>. This method returns the correct
+ * result for these cases.</p>
+ *
+ * <p><code>Null</code> may be assigned to any reference type. This method will
+ * return <code>true</code> if <code>null</code> is passed in and the toClass is
+ * non-primitive.</p>
+ *
+ * <p>Specifically, this method tests whether the type represented by the
+ * specified <code>Class</code> parameter can be converted to the type
+ * represented by this <code>Class</code> object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+ *
+ * @param classArray the array of Classes to check, may be <code>null</code>
+ * @param toClassArray the array of Classes to try to assign into, may be <code>null</code>
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return <code>true</code> if assignment possible
+ */
+ public static boolean isAssignable(Class[] classArray, Class[] toClassArray, boolean autoboxing) {
if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
return false;
}
@@ -403,7 +439,7 @@
toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
}
for (int i = 0; i < classArray.length; i++) {
- if (isAssignable(classArray[i], toClassArray[i]) == false) {
+ if (isAssignable(classArray[i], toClassArray[i], autoboxing) == false) {
return false;
}
}
@@ -437,12 +473,58 @@
* @return <code>true</code> if assignment possible
*/
public static boolean isAssignable(Class cls, Class toClass) {
+ return isAssignable(cls, toClass, false);
+ }
+
+ /**
+ * <p>Checks if one <code>Class</code> can be assigned to a variable of
+ * another <code>Class</code>.</p>
+ *
+ * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+ * this method takes into account widenings of primitive classes and
+ * <code>null</code>s.</p>
+ *
+ * <p>Primitive widenings allow an int to be assigned to a long, float or
+ * double. This method returns the correct result for these cases.</p>
+ *
+ * <p><code>Null</code> may be assigned to any reference type. This method
+ * will return <code>true</code> if <code>null</code> is passed in and the
+ * toClass is non-primitive.</p>
+ *
+ * <p>Specifically, this method tests whether the type represented by the
+ * specified <code>Class</code> parameter can be converted to the type
+ * represented by this <code>Class</code> object via an identity conversion
+ * widening primitive or widening reference conversion. See
+ * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+ * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+ *
+ * @param cls the Class to check, may be null
+ * @param toClass the Class to try to assign into, returns false if null
+ * @param autoboxing whether to use implicit autoboxing/unboxing between primitives and wrappers
+ * @return <code>true</code> if assignment possible
+ */
+ public static boolean isAssignable(Class cls, Class toClass, boolean autoboxing) {
if (toClass == null) {
return false;
}
// have to check for null, as isAssignableFrom doesn't
if (cls == null) {
return !(toClass.isPrimitive());
+ }
+ //autoboxing:
+ if (autoboxing) {
+ if (cls.isPrimitive() && !toClass.isPrimitive()) {
+ cls = primitiveToWrapper(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
+ if (toClass.isPrimitive() && !cls.isPrimitive()) {
+ cls = wrapperToPrimitive(cls);
+ if (cls == null) {
+ return false;
+ }
+ }
}
if (cls.equals(toClass)) {
return true;
Modified: commons/proper/lang/branches/LANG_POST_2_4/src/test/org/apache/commons/lang/ClassUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/branches/LANG_POST_2_4/src/test/org/apache/commons/lang/ClassUtilsTest.java?rev=638702&r1=638701&r2=638702&view=diff
==============================================================================
--- commons/proper/lang/branches/LANG_POST_2_4/src/test/org/apache/commons/lang/ClassUtilsTest.java (original)
+++ commons/proper/lang/branches/LANG_POST_2_4/src/test/org/apache/commons/lang/ClassUtilsTest.java Tue Mar 18 21:27:41 2008
@@ -254,6 +254,26 @@
assertTrue(ClassUtils.isAssignable(Boolean.class, Boolean.class));
}
+ public void test_isAssignable_Autoboxing() throws Exception {
+ assertFalse(ClassUtils.isAssignable((Class) null, null, true));
+ assertFalse(ClassUtils.isAssignable(String.class, null, true));
+
+ assertTrue(ClassUtils.isAssignable(null, Object.class, true));
+ assertTrue(ClassUtils.isAssignable(null, Integer.class, true));
+ assertFalse(ClassUtils.isAssignable(null, Integer.TYPE, true));
+ assertTrue(ClassUtils.isAssignable(String.class, Object.class, true));
+ assertTrue(ClassUtils.isAssignable(String.class, String.class, true));
+ assertFalse(ClassUtils.isAssignable(Object.class, String.class, true));
+ assertTrue(ClassUtils.isAssignable(Integer.TYPE, Integer.class, true));
+ assertTrue(ClassUtils.isAssignable(Integer.class, Integer.TYPE, true));
+ assertTrue(ClassUtils.isAssignable(Integer.TYPE, Integer.TYPE, true));
+ assertTrue(ClassUtils.isAssignable(Integer.class, Integer.class, true));
+ assertTrue(ClassUtils.isAssignable(Boolean.TYPE, Boolean.class, true));
+ assertTrue(ClassUtils.isAssignable(Boolean.class, Boolean.TYPE, true));
+ assertTrue(ClassUtils.isAssignable(Boolean.TYPE, Boolean.TYPE, true));
+ assertTrue(ClassUtils.isAssignable(Boolean.class, Boolean.class, true));
+ }
+
public void test_isAssignable_Widening() throws Exception {
// test byte conversions
assertFalse("byte -> char", ClassUtils.isAssignable(Byte.TYPE, Character.TYPE));
@@ -334,6 +354,88 @@
assertFalse("boolean -> float", ClassUtils.isAssignable(Boolean.TYPE, Float.TYPE));
assertFalse("boolean -> double", ClassUtils.isAssignable(Boolean.TYPE, Double.TYPE));
assertTrue("boolean -> boolean", ClassUtils.isAssignable(Boolean.TYPE, Boolean.TYPE));
+ }
+
+ public void test_isAssignable_Unboxing_Widening() throws Exception {
+ // test byte conversions
+ assertFalse("byte -> char", ClassUtils.isAssignable(Byte.class, Character.TYPE, true));
+ assertTrue("byte -> byte", ClassUtils.isAssignable(Byte.class, Byte.TYPE, true));
+ assertTrue("byte -> short", ClassUtils.isAssignable(Byte.class, Short.TYPE, true));
+ assertTrue("byte -> int", ClassUtils.isAssignable(Byte.class, Integer.TYPE, true));
+ assertTrue("byte -> long", ClassUtils.isAssignable(Byte.class, Long.TYPE, true));
+ assertTrue("byte -> float", ClassUtils.isAssignable(Byte.class, Float.TYPE, true));
+ assertTrue("byte -> double", ClassUtils.isAssignable(Byte.class, Double.TYPE, true));
+ assertFalse("byte -> boolean", ClassUtils.isAssignable(Byte.class, Boolean.TYPE, true));
+
+ // test short conversions
+ assertFalse("short -> char", ClassUtils.isAssignable(Short.class, Character.TYPE, true));
+ assertFalse("short -> byte", ClassUtils.isAssignable(Short.class, Byte.TYPE, true));
+ assertTrue("short -> short", ClassUtils.isAssignable(Short.class, Short.TYPE, true));
+ assertTrue("short -> int", ClassUtils.isAssignable(Short.class, Integer.TYPE, true));
+ assertTrue("short -> long", ClassUtils.isAssignable(Short.class, Long.TYPE, true));
+ assertTrue("short -> float", ClassUtils.isAssignable(Short.class, Float.TYPE, true));
+ assertTrue("short -> double", ClassUtils.isAssignable(Short.class, Double.TYPE, true));
+ assertFalse("short -> boolean", ClassUtils.isAssignable(Short.class, Boolean.TYPE, true));
+
+ // test char conversions
+ assertTrue("char -> char", ClassUtils.isAssignable(Character.class, Character.TYPE, true));
+ assertFalse("char -> byte", ClassUtils.isAssignable(Character.class, Byte.TYPE, true));
+ assertFalse("char -> short", ClassUtils.isAssignable(Character.class, Short.TYPE, true));
+ assertTrue("char -> int", ClassUtils.isAssignable(Character.class, Integer.TYPE, true));
+ assertTrue("char -> long", ClassUtils.isAssignable(Character.class, Long.TYPE, true));
+ assertTrue("char -> float", ClassUtils.isAssignable(Character.class, Float.TYPE, true));
+ assertTrue("char -> double", ClassUtils.isAssignable(Character.class, Double.TYPE, true));
+ assertFalse("char -> boolean", ClassUtils.isAssignable(Character.class, Boolean.TYPE, true));
+
+ // test int conversions
+ assertFalse("int -> char", ClassUtils.isAssignable(Integer.class, Character.TYPE, true));
+ assertFalse("int -> byte", ClassUtils.isAssignable(Integer.class, Byte.TYPE, true));
+ assertFalse("int -> short", ClassUtils.isAssignable(Integer.class, Short.TYPE, true));
+ assertTrue("int -> int", ClassUtils.isAssignable(Integer.class, Integer.TYPE, true));
+ assertTrue("int -> long", ClassUtils.isAssignable(Integer.class, Long.TYPE, true));
+ assertTrue("int -> float", ClassUtils.isAssignable(Integer.class, Float.TYPE, true));
+ assertTrue("int -> double", ClassUtils.isAssignable(Integer.class, Double.TYPE, true));
+ assertFalse("int -> boolean", ClassUtils.isAssignable(Integer.class, Boolean.TYPE, true));
+
+ // test long conversions
+ assertFalse("long -> char", ClassUtils.isAssignable(Long.class, Character.TYPE, true));
+ assertFalse("long -> byte", ClassUtils.isAssignable(Long.class, Byte.TYPE, true));
+ assertFalse("long -> short", ClassUtils.isAssignable(Long.class, Short.TYPE, true));
+ assertFalse("long -> int", ClassUtils.isAssignable(Long.class, Integer.TYPE, true));
+ assertTrue("long -> long", ClassUtils.isAssignable(Long.class, Long.TYPE, true));
+ assertTrue("long -> float", ClassUtils.isAssignable(Long.class, Float.TYPE, true));
+ assertTrue("long -> double", ClassUtils.isAssignable(Long.class, Double.TYPE, true));
+ assertFalse("long -> boolean", ClassUtils.isAssignable(Long.class, Boolean.TYPE, true));
+
+ // test float conversions
+ assertFalse("float -> char", ClassUtils.isAssignable(Float.class, Character.TYPE, true));
+ assertFalse("float -> byte", ClassUtils.isAssignable(Float.class, Byte.TYPE, true));
+ assertFalse("float -> short", ClassUtils.isAssignable(Float.class, Short.TYPE, true));
+ assertFalse("float -> int", ClassUtils.isAssignable(Float.class, Integer.TYPE, true));
+ assertFalse("float -> long", ClassUtils.isAssignable(Float.class, Long.TYPE, true));
+ assertTrue("float -> float", ClassUtils.isAssignable(Float.class, Float.TYPE, true));
+ assertTrue("float -> double", ClassUtils.isAssignable(Float.class, Double.TYPE, true));
+ assertFalse("float -> boolean", ClassUtils.isAssignable(Float.class, Boolean.TYPE, true));
+
+ // test double conversions
+ assertFalse("double -> char", ClassUtils.isAssignable(Double.class, Character.TYPE, true));
+ assertFalse("double -> byte", ClassUtils.isAssignable(Double.class, Byte.TYPE, true));
+ assertFalse("double -> short", ClassUtils.isAssignable(Double.class, Short.TYPE, true));
+ assertFalse("double -> int", ClassUtils.isAssignable(Double.class, Integer.TYPE, true));
+ assertFalse("double -> long", ClassUtils.isAssignable(Double.class, Long.TYPE, true));
+ assertFalse("double -> float", ClassUtils.isAssignable(Double.class, Float.TYPE, true));
+ assertTrue("double -> double", ClassUtils.isAssignable(Double.class, Double.TYPE, true));
+ assertFalse("double -> boolean", ClassUtils.isAssignable(Double.class, Boolean.TYPE, true));
+
+ // test boolean conversions
+ assertFalse("boolean -> char", ClassUtils.isAssignable(Boolean.class, Character.TYPE, true));
+ assertFalse("boolean -> byte", ClassUtils.isAssignable(Boolean.class, Byte.TYPE, true));
+ assertFalse("boolean -> short", ClassUtils.isAssignable(Boolean.class, Short.TYPE, true));
+ assertFalse("boolean -> int", ClassUtils.isAssignable(Boolean.class, Integer.TYPE, true));
+ assertFalse("boolean -> long", ClassUtils.isAssignable(Boolean.class, Long.TYPE, true));
+ assertFalse("boolean -> float", ClassUtils.isAssignable(Boolean.class, Float.TYPE, true));
+ assertFalse("boolean -> double", ClassUtils.isAssignable(Boolean.class, Double.TYPE, true));
+ assertTrue("boolean -> boolean", ClassUtils.isAssignable(Boolean.class, Boolean.TYPE, true));
}
public void testPrimitiveToWrapper() {