我正在尝试通过反射访问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?)。
我不确定我正在打破什么样的施法规则。如果我的地图条目具有不同的数字值(Integer
,Float
,Double
),请有人帮助我,但我需要方法返回double
值(原语) )。
PS 这不是真的重复。我的问题更为笼统。但是谢谢你的意见。我忘了invoke总是返回Object。
工作代码是:
return ((Number)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name)).doubleValue();
答案 0 :(得分:0)
您错误地假设您传递给Class
的{{1}}对象与getDeclaredMethod
的返回类型之间存在关联。
您传递给Method.invoke
或Class
的{{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();
使工作更有效率。