简体   繁体   中英

How to check if an Object instance is a valid return for a Method

I have an Object instance obj and a Method object method . How can I check to see if obj would be a valid return for the method ?

Assume method has no parameters and it's not a return type of void (confirmed as a getter).

For example, if obj is null then the return type for method cannot be a primitive. Alright, got that figured out. However, Class.isAssignableFrom does not take into account unboxing and boxing from primitives. For example int.class.isAssignableFrom(Integer.class) returns false, but that would be a valid return for the method.

An option I could take is use Class.cast but using exceptions for programming flow is rather nasty and generating exceptions is also costly. But it is something I am aware of.

I'm kind of stumped on exactly how to figure this all out elegantly. Help would be much appreciated.

The number of cases you have to handle, isn't that big. As you already mentioned, you must not return null if the return type is primitive. Then, you may consider unboxing, but don't have to deal with boxing as you already have an object to return (as always in reflective operations).

So the only additional case you have to check is whether the return type is a primitive type and the object is of the appropriate wrapper type. If you want to keep the code concise you can settle on the fact that every wrapper type has a field named TYPE containing the Class object of the corresponding primitive type:

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);
}

The code above takes some short-cuts. If the value is null we can immediately check the only constraint that the return type must not be a primitive type. Otherwise, we can safely assume that we have a non- null object and if its type happens to be an exact match of the return type, we short-cut the rest. If the return type is not a primitive type a simple isAssignableFrom will do. But if the return type is a primitive type, we optimistically try to read the field TYPE , assuming a wrapper type and compare. Any failure indicates that the actual type is not a wrapper type.


Of course, this Reflective check is concise but not the best coding style and doesn't promise good performance. It's only good for some ad-hoc checks. If you want to use that check more often and/or in production code, the best solution remains a manually filled map:

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);
}

Doesn't this work for you? - https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#isInstance(java.lang.Object)

This doesn't raise exceptions and does exactly what you expect.

You can use the operator instanceof in order to check whether the return object is an instance (or inherited from) your expected result type.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM