对具有原始数字返回类型的方法的反思 [英] Reflection on methods with a primitive numeric return type

查看:125
本文介绍了对具有原始数字返回类型的方法的反思的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个小型框架来收集OSGi系统中的指标。
它的核心是注释@Metric,它表示服务的给定方法在被询问时可以提供度量(例如数值)。

I'm currently working on a small framework to collect metrics in an OSGi system. The core of it is an annotation @Metric that indicates that a given method of a service can deliver a metric (e.g. numeric value) when asked.

那些方法如下:

@Metric
public int getQueueSize() {...}

@Metric
public double getAvgTaskTime() {...}

我正在使用反射来检查服务实现类并注册用 @Metric 注释的方法。作为一个完整性检查,我正在检查该方法确实提供了一个数值。我试过这个并且失败了:

I'm using reflection to inspect the service implementation class and register the methods that are annotated with @Metric. As a sanity check, I'm checking that the method indeed delivers a numeric value. I tried this and failed:

for (Method method: metricSource.getClass().getMethods()) {
    if (method.isAnnotationPresent(Metric.class) &&  Number.class.isAssignableFrom(method.getReturnType()) { 
        // add method for later process
    }

然后,稍后在处理器上,我会这样做:

Then, later on the processor, I'd do:

Number value = (Number) method.invoke(target, obj[]);

事实证明,对于原始类型,您将获得例如 int.class ,并且这不能分配给Number.class,而盒装类型Integer.class将是。该死的。继续前进。

It turns out that for a primitive type you would get e.g. int.class and that's not assignable to Number.class whereas the boxed type Integer.class would be. Damn. Move on.

然后我创建了一个 Map< Class<?> ;,Oxtractor> ,其中Extractor采取一个类并将一个参数强制转换为该类:

Then I created a Map<Class<?>, Extractor> where Extractor takes a class and casts a parameter into that class:

public NumberExtractor(Class<? extends Number> clazz) {
    this.clazz = clazz;
    }       
    public double extract(Object val) {
        Number nbr = clazz.cast(val);
        return nbr.doubleValue();
    }
}

面对之前的观察,我添加了一个条目像这样:

In face of the previous observation, I added an entry like this:

extractorMap.put(int.class, new NumberExtractor(int.class));

但这也不起作用。它给出了一个运行时类强制转换异常,说Integer.class无法强制转换为int。另请注意,编译器不会在新的NumberExtractor(int.class)上抱怨,让边界检查 Class<? extends Number> 传递 int.class

But that didn't work either. It gave a runtime class cast exception saying that Integer.class could not be cast to int. Note also that the compiler does not complain on new NumberExtractor(int.class), letting the boundary check Class<? extends Number> pass on int.class

最后,这个组合起作用了:

At the end, this combination worked:

extractorMap.put(int.class, new NumberExtractor(Integer.class));

这里发生了什么? Reflection说对象的返回类型(int.class)不能赋值给Number.class,但是当我继续调用方法时,我实际上得到了一个Integer.class? WhiskeyTangoFoxtrot?!

What is going on here? Reflection says that the return type of the object (int.class) is not assignable to Number.class, but when I go on with the method invoke, I actually get a Integer.class? WhiskeyTangoFoxtrot?!

我想知道是否有另一种方法可以解决这个问题,除了维护int的地图 - >整数,整数 - >整数,浮点数 - >漂浮,漂浮 - >漂浮? (现在已经完成了,所以这是为了学习)

I'm left wondering whether there is another way to address this issue other than maintaining the Map of int -> Integer, Integer -> Integer, float -> Float, Float -> Float? (which is now done, so this is for the sake of learning)

拳击和类型信息的行为在这里似乎并不一致。

The behaviour of the boxing and type information doesn't seem coherent here.

有人可以对此有所了解吗?

Could anybody shine some light on this?

推荐答案


Reflection说对象的返回类型(int.class)不能赋值给Number.class,但是当我继续调用方法时,我实际上得到了一个Integer.class?

Reflection says that the return type of the object (int.class) is not assignable to Number.class, but when I go on with the method invoke, I actually get a Integer.class?

绝对。反射API不能可能返回一个实际的 int ,因此它将该值设置为 Integer 。它还能做什么?

Absolutely. The reflection API can't possibly return you an actual int, so it boxes the value in an Integer. What else could it do?

它必须装箱改变 int的可转让性数字。查看 <$ c的文档$ c> isAssignableFrom

The fact that it has to box does not change the assignability from int to Number. Look at the docs for isAssignableFrom:


如果此Class对象表示基本类型,则此方法返回如果指定的Class参数恰好是此Class对象,则返回true;否则它返回false。

If this Class object represents a primitive type, this method returns true if the specified Class parameter is exactly this Class object; otherwise it returns false.

所以它的行为完全符合文档。

So it's behaving exactly according to the documentation.

我想知道是否还有其他方法可以解决这个问题,而不是维护Map的地图 - >整数,整数 - >整数,浮点数 - >浮点数,浮点数 - >浮点数? (现在已经完成了,所以这是为了学习)

I'm left wondering whether there is another way to address this issue other than maintaining the Map of int -> Integer, Integer -> Integer, float -> Float, Float -> Float? (which is now done, so this is for the sake of learning)

是的,这对我来说是对的。或者只是为原始数字类型设置 Set< Class> 而不是显式映射。

Yup, that sounds right to me. Or just have a Set<Class> for primitive numeric types rather than explicitly mapping.

这篇关于对具有原始数字返回类型的方法的反思的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆