如何检查Object实例是否是Method的有效返回

时间:2016-04-25 13:42:23

标签: java reflection

我有一个Object实例obj和一个Method对象method。如何查看objmethod的有效回报?

假设method没有参数,并且它不是void的返回类型(确认为getter)。

例如,如果objnull,则method的返回类型不能是原语。好吧,弄清楚了。但是,Class.isAssignableFrom没有考虑从基元中取消装箱和装箱。例如,int.class.isAssignableFrom(Integer.class)返回false,但这将是该方法的有效返回。

我可以使用的选项是使用Class.cast但是使用编程流程的异常是相当讨厌的,并且生成异常也是昂贵的。但这是我所知道的。

我有点难以理解如何优雅地解决这个问题。非常感谢帮助。

3 个答案:

答案 0 :(得分:1)

你需要处理的案件数量并不大。正如您已经提到的,如果返回类型是原始的,则不能返回null。然后,您可以考虑取消装箱,但不必处理装箱,因为您已经有一个要返回的对象(如同在反射操作中一样)。

因此,您必须检查的唯一额外情况是返回类型是否是基本类型,并且对象是否是适当的包装类型。如果您希望保持代码简洁,您可以确定每个包装类型都有一个名为TYPE的字段,其中包含相应基元类型的Class对象:

static boolean canReturn(Method m, Object value) {
    Class<?> rt=m.getReturnType();
    if(value==null) return !rt.isPrimitive();
    Class<?> act=value.getClass();
    if(rt==act) return true;
    if(rt.isPrimitive()) try {
        return act.getDeclaredField("TYPE").get(null)==rt;
    } catch(ReflectiveOperationException | NullPointerException ex) {
        return false;
    }
    return rt.isAssignableFrom(act);
}

上面的代码采取了一些捷径。如果值为null,我们可以立即检查返回类型不能是基本类型的唯一约束。否则,我们可以安全地假设我们有一个非null对象,如果它的类型碰巧与返回类型完全匹配,我们将其余部分缩短。如果返回类型不是原始类型,则简单isAssignableFrom将执行。但是如果返回类型是基本类型,我们乐观地尝试读取字段TYPE,假设包装类型并进行比较。任何失败都表示实际类型不是包装类型。

当然,这种反光检查很简洁,但不是最好的编码风格,也不保证良好的性能。它只适用于一些临时检查。如果您想更频繁地和/或在生产代码中使用该检查,最佳解决方案仍然是手动填充的地图:

static final Map<Class<?>,Class<?>> PRIMITIVE2WRAPPER;
static {
    Map<Class<?>,Class<?>> p2w=new HashMap<>();
    p2w.put(boolean.class, Boolean.class);
    p2w.put(byte.class, Byte.class);
    p2w.put(short.class, Short.class);
    p2w.put(char.class, Character.class);
    p2w.put(int.class, Integer.class);
    p2w.put(long.class, Long.class);
    p2w.put(float.class, Float.class);
    p2w.put(double.class, Double.class);
    PRIMITIVE2WRAPPER=Collections.unmodifiableMap(p2w);
}
static boolean canReturn(Method m, Object value) {
    Class<?> rt=m.getReturnType();
    if(value==null) return !rt.isPrimitive();
    Class<?> act=value.getClass();
    if(rt==act) return true;
    return rt.isPrimitive()? PRIMITIVE2WRAPPER.get(rt)==act: rt.isAssignableFrom(act);
}

答案 1 :(得分:-1)

这不适合你吗? - https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#isInstance(java.lang.Object)

这不会引发异常并完全符合您的预期。

答案 2 :(得分:-1)

您可以使用运算符instanceof来检查返回对象是否是您的预期结果类型的实例(或继承自)。

if (obj instanceof ExpectedResultClass) {
    //do your stuff
}