简体   繁体   English

如何检查地图类型是否扩展了Number

[英]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 . 但是,对于其他两种情况的doublesannonDoubles ,包含在其他答案中的反射代码应该到达TDouble分配。

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.

相关问题 如何查看地图类型? - How to check the map type? 如何创建&lt;T扩展Map &lt;? ,? &gt;&gt; Map类型容器的类型拆分操作? - How can I create < T extends Map < ? , ? > > type split operation for Map type container? 如何检查一个类是否扩展了另一个类 - How to Check if a class extends another 为什么列出 <Map<? extends Number,? extends Number> &gt;不适用于列表 <Map<Integer,Double> &gt; - Why List<Map<? extends Number,? extends Number>> is not working for List<Map<Integer,Double>> 泛型-如何将地图转移到地图? 延伸x? - Generics - How to transfer map to map with ? extends x? 如何在JAVA泛型中定义使用2个泛型参数扩展Map对象的类型? - How can I define in JAVA generic type that extends Map object with 2 generic parameters? Dagger 2:如何注入Map <Class <?扩展Foo>,Provider <?延伸Foo >> - Dagger 2: How to inject Map<Class<? extends Foo>, Provider<? extends Foo>> 如何检查字符串代表的数字和数字类型? - How to check if and what type of number a string represents? 如何检查数字是否适合Java中的原始类型? - How to check if number fits primitive type in java? 如何检查数字是否超出整数类型的范围? - How to check a number is out of the range of Integer type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM