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.
精彩评论