|
Description
|
A DESCRIPTION OF THE REQUEST :
There is no generic means of getting the wrapper type for a primitive class or the wrapped primitive type for a wrapper class. I propose adding the following methods to java.lang.Class:
public boolean isWrapper ()
public Class<?> getWrapperType ()
public Class<?> getWrappedType ()
isPrimitiveWrapper would return true for the java.lang types Boolean, Byte, Short, Character, Integer, Long, Float, and Double. It would return false for all other types.
getWrapperType would return null for all classes except the eight primitive types Boolean.TYPE, Byte.TYPE, Short.TYPE, Character.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, and Double.TYPE which would return the corresponding java.lang wrapper types Boolean, Byte, Short, Character, Integer, Long, Float, and Double, respectively.
getWrappedType would return null for all classes except the eight java.lang wrapper types Boolean, Byte, Short, Character, Integer, Long, Float, and Double which would return the corresponding primitive types Boolean.TYPE, Byte.TYPE, Short.TYPE, Character.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, and Double.TYPE, respectively.
Alternative names for the proposed methods are:
public boolean isPrimitiveWrapper ()
public Class<?> getPrimitiveWrapperType ()
public Class<?> getWrappedPrimitiveType ()
JUSTIFICATION :
When using reflection, primitive values for Field values and for Method parameters and return types are wrapped (e.g. calling the invoke method on a java.lang.reflect.Method customer for a method with the signature int foo() returns an an Integer customer containing the int value). Certain programming constructs using reflection are inelegant without a means to convert the actual type to the reflected type (see example).
Since the wrapper types are integral to the Java language (even more so with the addition of auto {un}boxing), it is reasonable and useful to provide support for primitive wrapper type conversion as part of the language reflection mechanism.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
// I realize this simple example is not required to check for a Comparable
// Field in the constructor as it can simply throw a ClassCastException
// from compare, but I was trying to keep the example simple.
import java.lang.reflect.Field;
import java.util.Comparator;
public class GenericComparator implements Comparator, java.io.Serializable {
private final Field field;
public GenericComparator (Field field) {
Class type = field.getType();
if (type.isPrimitive())
type = type.getWrapper();
if (!Comparable.class.isAssignableFrom(type))
throw new IllegalArgumentException("Field type must be Comparable");
this.field = field;
}
public int compare (Object obj1, Object obj2) {
try {
Comparable comp1 = (Comparable) field.get(obj1);
return comp1.compareTo(field.get(obj2));
}
catch (IllegalAccessException ex) {
throw (ClassCastException) new ClassCastException().initCause(ex);
}
}
}
ACTUAL -
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.Map;
import java.util.HashMap;
public class GenericComparator implements Comparator, java.io.Serializable {
private static final Map<Class, Class> WRAPPERS = new HashMap<Class, Class>();
static {
WRAPPERS.put(byte.class, Byte.class);
WRAPPERS.put(short.class, Short.class);
WRAPPERS.put(char.class, Character.class);
WRAPPERS.put(int.class, Integer.class);
WRAPPERS.put(long.class, Long.class);
WRAPPERS.put(float.class, Float.class);
WRAPPERS.put(double.class, Double.class);
WRAPPERS.put(boolean.class, Boolean.class);
}
private final Field field;
public GenericComparator (Field field) {
Class type = field.getType();
if (type.isPrimitive())
type = WRAPPERS.get(type);
if (!Comparable.class.isAssignableFrom(type))
throw new IllegalArgumentException("Field type must be Comparable");
this.field = field;
}
public int compare (Object obj1, Object obj2) {
try {
Comparable comp1 = (Comparable) field.get(obj1);
return comp1.compareTo(field.get(obj2));
}
catch (IllegalAccessException ex) {
throw (ClassCastException) new ClassCastException().initCause(ex);
}
}
}
CUSTOMER SUBMITTED WORKAROUND :
The work around is to declare and initialize a HashMap to contain the desired mapping from primitive class to wrapper class and/or from wrapper class to primitive class.
xxxxx@xxxxx 10/11/04 16:43 GMT
|
|
Comments
|
Submitted On 11-SEP-2005
Suggestion:
There is an implied common base type (Float, Integer, Char, etc all extend/implements 'PrimitiveWrapper').
We should therefore be able to just test that the Class implements that type instead of adding the method isPrimitiveWrapper().
Submitted On 06-JUL-2006
McNepp
>Suggestion:
>There is an implied common base type (Float, Integer, Char, etc all extend/implements 'PrimitiveWrapper').
>We should therefore be able to just test that the Class implements that type instead of adding the method isPrimitiveWrapper().
All class objects share the same type (java.lang.Class). In order to make your suggestion possible, you'd have to remove [b]final[/b java.lang.Class and change the way the class objects are created and maintained at runtime. It would also affect serialization if there were different Class types.
Submitted On 22-FEB-2007
daniel_l_smith
> All class objects share the same type (java.lang.Class). ...
I took the original suggestion to be adding a PrimitiveWrapper interface that
Byte, Float, Boolean, Void, etc. would implement. Then checking whether a
Class is a wrapper could be done with
PrimitiveWrapper.class.isAssignableFrom(c)
Submitted On 29-NOV-2007
I have encountered the issue too and blogged some observations here:
http://sensualjava.blogspot.com/2007/11/reflection-and-auto-boxing.html
I propose to create a java.lang.reflect.Primitive class with static utility methods that will support widening primitive conversions, boxing and un-boxing as defined in Java Language Specification chapter 5.1.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|