将数字转换为双原语

时间:2016-06-01 19:21:01

标签: java reflection casting

我正在尝试通过反射访问HashMap<String, Number>

Serializable obj; //here goes the HashMap
String name;
...
return (double)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name);

但到目前为止,我得到的是由上面一行引起的投射错误:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double

实际上,密钥name访问的地图值为Integer。所以我已将该行更改为:

return obj.getClass().getDeclaredMethod("get", Number.class).invoke(obj, name).doubleValue();

但这也没有成功。我甚至将doubleValue()加下划线为“未定义类型对象”(但是为什么对象,如果我有Number.class?)。

我不确定我正在打破什么样的施法规则。如果我的地图条目具有不同的数字值(IntegerFloatDouble),请有人帮助我,但我需要方法返回double值(原语) )。

PS 这不是真的重复。我的问题更为笼统。但是谢谢你的意见。我忘了invoke总是返回Object。

工作代码是:

return ((Number)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name)).doubleValue();

1 个答案:

答案 0 :(得分:0)

您错误地假设您传递给Class的{​​{1}}对象与getDeclaredMethod的返回类型之间存在关联。 您传递给Method.invokeClass的{​​{1}}个对象描述了方法的参数类型,而不是返回类型。 此外,虽然您可以传递声明的参数类型的子类型的参数,但您必须准确指定声明的参数类型。

Map.get的参数类型总是getMethod,因此您必须指定getDeclaredMethod,无论您将哪个实际密钥传递给Object

此外,由于类型擦除,无论实际Object.class的参数化如何,反射返回类型始终为invoke。 并非重要,Method.invoke声明的返回类型始终为Object,因为不同的Map实例可能代表不同的方法。

因此,当您拥有Object时,您可以依赖返回的对象为Method个实例,但不一定是HashMap<String, Number>个实例。根据您的经验,可能会有Number个实例。所以你要做的就是输入到Double,然后调用Integer

Number

也就是说,如果您知道该对象实现了doubleValue()接口,则根本没有理由使用Reflection:

return ((Number)obj.getClass().getDeclaredMethod("get", Object.class)
        .invoke(obj, name)).doubleValue();

使工作更有效率。