对具有原始数字返回类型的方法的反思

maa*_*asg 9 java reflection primitive-types

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

这些方法看起来像:

@Metric
public int getQueueSize() {...}
Run Code Online (Sandbox Code Playgroud)

要么

@Metric
public double getAvgTaskTime() {...}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Number value = (Number) method.invoke(target, obj[]);
Run Code Online (Sandbox Code Playgroud)

事实证明,对于一个原始类型,你会得到eg int.class,而且不能赋予Number.class,而盒装类型Integer.class则是.该死的.继续.

然后我创建了一个Map<Class<?>, Extractor>Extractor取一个类并将参数强制转换为该类的地方:

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

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

extractorMap.put(int.class, new NumberExtractor(int.class));
Run Code Online (Sandbox Code Playgroud)

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

最后,这个组合工作:

extractorMap.put(int.class, new NumberExtractor(Integer.class));
Run Code Online (Sandbox Code Playgroud)

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

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

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

有人可以对此有所启发吗?

Jon*_*eet 10

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

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

它有框是否事实并非可转让性的变化intNumber.查看文档isAssignableFrom:

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

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

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

是的,这对我来说是对的.或者只是使用Set<Class>原始数字类型而不是显式映射.