[英]Casting Number to double primitive
I'm trying to access a HashMap<String, Number>
via reflection: 我试图通过反射访问HashMap<String, Number>
:
Serializable obj; //here goes the HashMap
String name;
...
return (double)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name);
but so far all I got is a casting error caused by the line above: 但到目前为止,我所得到的只是由上述行引起的转换错误:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double
Indeed, the map value that was accessed by the key name
was Integer
.So I've changed the line to: 实际上,键name
访问的映射值是Integer
我将行更改为:
return obj.getClass().getDeclaredMethod("get", Number.class).invoke(obj, name).doubleValue();
but that didn't work out either. 但这也不可行。 I even got doubleValue()
underlined as "undefined for the type Object" (but why Object if I have Number.class?). 我什至在doubleValue()
下划线标有“类型对象未定义”的下划线(但是如果我有Number.class,为什么还要选择对象?)。
I'm not sure what casting rules I'm breaking. 我不确定我要打破哪些强制转换规则。 Can someone, please, help me if my map entries have various number values ( Integer
, Float
, Double
) but I need the method to return a double
value (primitive). 如果我的地图条目具有各种数字值( Integer
, Float
, Double
),但是有人需要帮助我,但是我需要返回double
值(原始)的方法。
PS It's not really a duplicate. PS这不是真正的重复。 My question is more general. 我的问题更笼统。 But thank you for your input. 但是,谢谢您的投入。 I forgot that invoke always returns Object. 我忘记了调用总是返回Object。
The working code is: 工作代码为:
return ((Number)obj.getClass().getDeclaredMethod("get", Object.class).invoke(obj, name)).doubleValue();
You have the wrong assumption that there was a relationship between the Class
object you pass to getDeclaredMethod
and the return type of Method.invoke
. 您错误地假设传递给getDeclaredMethod
的Class
对象与Method.invoke
的返回类型之间存在关联。 The Class
objects you pass to getMethod
or getDeclaredMethod
describe the parameter types of the method, not the return type. 传递给getMethod
或getDeclaredMethod
的Class
对象描述方法的参数类型,而不是返回类型。 Further, while you may pass arguments of a subtype of the declared parameter type, you have to specify exactly the declared parameter type. 此外,尽管您可以传递已声明参数类型的子类型的参数,但必须准确指定已声明参数类型。
The parameter type of Map.get
is Object
, invariably, so you have to specify Object.class
, regardless of which actual key you will pass to invoke
. Map.get
的参数类型Map.get
是Object
,因此无论要传递哪个实际键来invoke
,都必须指定Object.class
。
Further, due to type erasure, the reflective return type will always be Object
, regardless of the actual Map
's parametrization. 此外,由于类型擦除,无论实际Map
的参数化如何,反射返回类型将始终为Object
。 Not that it matters, Method.invoke
's declared return type is always Object
, as different Method
instances may represent different methods. Method.invoke
, Method.invoke
的声明的返回类型始终为Object
,因为不同的Method
实例可能表示不同的方法。
So when you have a HashMap<String, Number>
, you can rely on the returned objects to be Number
instances, but not necessarily Double
instances. 因此,当您具有HashMap<String, Number>
,可以将返回的对象作为Number
实例,但不一定要是Double
实例。 As you experienced, there could be Integer
instances. 如您所料,可能存在Integer
实例。 So what you have to do, is to type-cast to Number
, followed by invoking doubleValue()
: 因此,您要做的是将类型转换为Number
,然后调用doubleValue()
:
return ((Number)obj.getClass().getDeclaredMethod("get", Object.class)
.invoke(obj, name)).doubleValue();
That said, if you know that the object implements the Map
interface, there is no reason to use Reflection at all: 就是说,如果您知道该对象实现了Map
接口,则完全没有理由使用Reflection:
return ((Number)((Map<?,?>)obj).get(name)).doubleValue();
does the job much more efficient. 可以使工作效率更高。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.