开发者

Cannot cast java.lang.Float to float when using Class.cast?

I already have a solution, but I don't like it. Also, it would be nice to know your thoug开发者_运维知识库hts about this.

You see, elem.get gives back an Object, that is going to be a Float in the case of x and y.

This code throws the Exception described in the title:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);
        arg.add(types[i].cast(elem.get(names[i])));
    }
}

The code is used to define the list of parameters to instantiate an object. Both the parameters and the object's class name are defined in an external data file (but nevermind about that).

The solution, something I'm not fond of (because it loses the flexibility I was trying to attain), has this within the for:

if(types[i] == float.class)
{
    float v = (Float)elem.get(names[i]);
    arg.add(v);
} else
{
    arg.add(types[i].cast(elem.get(names[i])));
    break;
}

Other option would be changing float.class to Float.class in types, but I won't do that because that code is used to instantiate objects which have float parameters in their constructors.

Thanks!


As the type of args is an ArrayList<Object>, you're not avoiding the boxing anyway:

// This code...
float v = (Float)elem.get(names[i]);
arg.add(v);

// Will actually be equivalent to:
float v = (Float)elem.get(names[i]);
Float boxed = v;
arg.add(boxed);

If the point is to call a constructor by reflection, then you're going to have to pass in a Float for any float parameters - that's just how it works.

So basically, change float.class to Float.class and it should all work fine. EDIT: Ah, except then the par list will have the wrong type. Basically you want to cast with Float.class, but add float.class to the list of parameter types.

You probably want a map from primitive types to wrapper types, like this:

private static final Map<Class<?>>, Class<?>> PRIMITIVE_TYPE_MAP =
    buildPrimitiveTypeMap();

private static Map<Class<?>>, Class<?>> buildPrimitiveTypeMap()
{
    Map<Class<?>>, Class<?>> map = new HashMap<Class<?>>, Class<?>>();
    map.put(float.class, Float.class);
    map.put(double.class, Double.class);
    // etc
    return map;
}

Then:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);

        // For primitive types, only box to the wrapper type
        Class<?> castType = PRIMITIVE_TYPE_MAP.get(types[i]);
        if (castType == null)
        {
            castType = types[i];
        }
        arg.add(castType.cast(elem.get(names[i])));
    }
}

In fact, if you trust that the values are of the right type already, I suspect you can just do:

arg.add(elem.get(names[i]));

After all, you're just casting to a particular type and then losing that type information again... using the cast call does perform a check that the execution-time types are correct though, so you may want to keep it for that reason.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜