简体   繁体   English

将数字转换为双基元

[英]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). 如果我的地图条目具有各种数字值( IntegerFloatDouble ),但是有人需要帮助我,但是我需要返回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 . 您错误地假设传递给getDeclaredMethodClass对象与Method.invoke的返回类型之间存在关联。 The Class objects you pass to getMethod or getDeclaredMethod describe the parameter types of the method, not the return type. 传递给getMethodgetDeclaredMethodClass对象描述方法的参数类型,而不是返回类型。 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.getObject ,因此无论要传递哪个实际键来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.invokeMethod.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM