[英]How to Check if type of Map extends Number
I'm trying to check if a Map<String, T>
contains Objects (T) of type Double or Integer. 我正在尝试检查
Map<String, T>
包含Double或Integer类型的对象(T)。
I don't want to use the actual Objects in the map for checking the class since It's not certain that the Map contains Objects at all. 我不希望使用地图中的实际Objects来检查类,因为不确定Map是否包含Objects。
I can achieve this by doing the following (Assuming the field is containing a Map): 我可以通过执行以下操作(假设该字段包含一个Map)来实现:
ParameterizedType type = (ParameterizedType) field.getGenericType();
isNumeric(type);
/**
* @param type
* @return Returns true if type is numeric
*/
private static boolean isNumeric(ParameterizedType type) {
return type.getActualTypeArguments()[1].toString().equals("? extends java.lang.Number");
}
It's sufficient for me but it doesn't feel like a clean solution. 这对我来说已经足够了,但是感觉不像是一个干净的解决方案。
However, I can retrieve the Type of the getActualTypeArguments()[1]
by doing the following: 但是,我可以通过执行以下操作来检索
getActualTypeArguments()[1]
的类型:
Type typeOfSecondGeneric = type.getActualTypeArguments()[1]; // equals '? extends java.lang.Number'
I can't use Number.class.isAssignableFrom(typeOfSecondGeneric); // Class expected
我不能使用
Number.class.isAssignableFrom(typeOfSecondGeneric); // Class expected
Number.class.isAssignableFrom(typeOfSecondGeneric); // Class expected
After I researched a bit, I didn't came up with a better solution than doing the String comparison. 经过一番研究之后,我没有想到比进行String比较更好的解决方案。
What am I getting wrong? 我怎么了?
Help is appreciated! 感谢帮助!
An ad hoc solution could be something like this: 临时解决方案可能是这样的:
private static boolean isNumericValue(ParameterizedType t) {
return isSubclassOf(t.getActualTypeArguments()[1], Number.class);
}
private static boolean isSubclassOf(Type t, Class<?> clazz) {
if (t instanceof Class<?>)
return clazz.isAssignableFrom((Class<?>) t);
if (t instanceof ParameterizedType)
return isSubclassOf(((ParameterizedType) t).getRawType(), clazz);
Type[] bounds = null;
if (t instanceof TypeVariable<?>)
bounds = ((TypeVariable<?>) t).getBounds();
if (t instanceof WildcardType)
bounds = ((WildcardType) t).getUpperBounds();
if (bounds != null && bounds.length > 0)
return isSubclassOf(bounds[0], clazz);
return clazz == Object.class;
}
That short example doesn't handle interface types or generic array types. 这个简短的示例不处理接口类型或通用数组类型。 It's also nowhere near to being complete with respect to the actual rules of subtyping.
就子类型的实际规则而言,它还远远不够完善。
If it's true that you really do need something like this, I think the better solution is to use Guava TypeToken
: 如果确实确实需要这样的东西,我认为更好的解决方案是使用Guava
TypeToken
:
private static final TypeToken<Map<?, ? extends Number>> T =
new TypeToken<Map<?, ? extends Number>>() {};
private static boolean isNumericValue(ParameterizedType t) {
return T.isSupertypeOf(t);
}
That said, I'm not all that convinced that you do need this. 就是说,我并不是所有人都相信您确实需要这样做。 This looks like an XY problem and you might do better asking a question about the problem you're trying to solve rather than your attempted solution.
这看起来像是XY问题 ,您可能最好问一个有关您要解决的问题的问题,而不是尝试解决的问题。 This is the kind of code that can turn in to a huge pain in the neck after your program is tied down to using it, especially if it's pervasive.
在您的程序无法使用之后,这种代码可能会变成巨大的麻烦,尤其是在无处不在的情况下。
This information is lost at run-time so in general you won't be able to figure out what T
really is. 该信息在运行时会丢失,因此通常您将无法弄清楚
T
到底是什么。
The exception to this general rule are limited to those case in where the map object class itself has a more specific constraint on that T
. 该通用规则的例外情况仅限于地图对象类本身对该
T
具有更特定约束的情况。 For example: 例如:
class MyDoubleMap<K> extends Map<K, Double> {
...
}
...
Map<String, Double> standard = new HashMap<>();
Map<String, Double> doubles = new MyDoubleMap<>();
Map<String, Double> annonDoubles = new HashMap<>() {};
With standard
any reflection trick won't be able to recover more than T
and that it could be anything that extends Object
. 使用
standard
任何反射技巧都无法恢复超过T
,并且它可以是任何扩展Object
东西。
However for the other two cases doubles
and annonDoubles
the reflection code included in other answer should get to the Double
assignation to the T
. 但是,对于其他两种情况的
doubles
和annonDoubles
,包含在其他答案中的反射代码应该到达T
的Double
分配。
With doubles
it should be easy to see that that information should be available thru reflection as it is integral part of this declaration of MyDoubleMap
. 使用
doubles
,应该很容易看出该信息应该通过反射获得,因为它是MyDoubleMap
声明的组成部分。 Perhaps annonDoubles
is a bit less obvious but in fact with the trailing {}
it is effectively declaring an anonymous inner class that extends HashMap<String, Double>
and so such an information for T
(and also for K
) can be recovered by reflection. 也许
annonDoubles
不太明显,但是实际上在结尾的{}
它实际上是在声明一个扩展HashMap<String, Double>
的匿名内部类,因此可以通过反射来恢复T
(以及K
)的此类信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.