Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6176992
Votes 4
Synopsis (reflect) Add support to java.lang.Class for wrapper type conversions
Category java:classes_lang
Reported Against 1.3 , 1.1.6 , mustang
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 3-Medium
Related Bugs 6260938 , 6361826 , 4207220 , 6409411 , 6456930 , 6181716 , 6189041
Submit Date 11-OCT-2004
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
Work Around
N/A
Evaluation
Under consideration.
Posted Date : 2005-12-02 05:23:58.0

Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=12007&forumID=1463
Posted Date : 2006-03-15 04:09:28.0

Will consider for Dolphin.
Posted Date : 2006-08-09 00:11:40.0
Comments
  
  Include a link with my name & email   

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