0

I intend to make a common dynamic null check function on any object before doing some work on it.

For example:

Class A{
 B b;

 // with getters and setters of b
}

class B{
C c;
//with getters and setters of c
}

class C{

  BigInteger d;

//with getters and setters of d
}

now, I want to check whether objA.getB().getC().getD() returns some value or throws NullPointerException?

By common I mean I can pass any kind of object to it, something like below function

CheckNull.checkingDynamicNull( "objA.getB().getC().getD()" ) 

will return me true or false depending on the case.

Any ideas?

Tom
  • 26,212
  • 21
  • 100
  • 111
advaita
  • 87
  • 1
  • 13
  • `objA.getB().getC().getD() == null` – Grijesh Chauhan Feb 15 '13 at 09:43
  • 1
    @GrijeshChauhan.. And what if `getB()` returned a `null`? – Rohit Jain Feb 15 '13 at 09:43
  • that is what i want to handle by returning false through that function.... – advaita Feb 15 '13 at 09:45
  • Any kind of dynamic null-check using (getter) methods may fail any time the methods have side-effects. So you probably come best off when you check each method individually. Using reflection and public fields this check may be possible. – Martin Nyolt Feb 15 '13 at 09:50
  • It doesn't sound like a very good approach. Surely you care which one is null? Won't that affect how you handle it being null? ie. if flight.family.person.baggage is null, that's probably fine - this person just doesn't have any baggage. But if flight.family.person is null, that means a family hasn't got any people - which is a serious error. – David Lavender Feb 15 '13 at 09:50
  • Reflection should be avoided whenever possible. Using method reference in Lambda expressions in Java 8 may make this kind of checking feasible. Until then, either lump it with the rest of use or make your life a little easier with some of the null checking in Google's Guava library. – KidTempo Feb 15 '13 at 10:07

6 Answers6

1

Unfortunately it is not possible to pass a funktion into a method in Java (yet, Java 8 will). Also, if you pass the variable name as String this wont work, since the recieving method has no way of knowing what Object is mapped to that variable (if you ignore reflection but even with that you are screwed if its a local variable).

Another way would be to do something like this

boolean nullCheck(Object obj, String Methods)

and then parse the String to Methods and invoke them on the object. But that wont work if you have Methods with arguments.

In short: It's more trouble then it's worth

In the most cases you want to have something like this

if(object == null){
    //error behavior
}

This assumes that you want to throw a certain Exception, have means to get a value for the null object elswhere or want to do something before you throw an exception. If you simply want to throw an Exception (that is not a NullPointerException)

assert object != null
Blank Chisui
  • 1,043
  • 10
  • 25
0

What about this:

public boolean checkingDynamicNull(A objA) {
    try {
        objA.getB().getC().getD().toString();
    } catch(NullPointerException npe) {
        return true;
    }
    return false;
}
oliholz
  • 7,447
  • 2
  • 43
  • 82
0

To know if a statement would return null, you would have to execute it first. Even if you somehow manage to execute the statement given in String to your method, it would be no different than just running it and checking whether the result is null, or catching the NullPointerException.

Erkan Haspulat
  • 12,032
  • 6
  • 39
  • 45
0

You are looking for something that will be part of Java 8 (or 9 or 10?) soon. Cf. http://viralpatel.net/blogs/null-safe-type-java-7-nullpointerexception/

C-Otto
  • 5,615
  • 3
  • 29
  • 62
0

With reflection it could be something like that:

nullCheck(objA, "getB", "getC", "getD" );

public static boolean nullCheck(Object obj, String... methods) {
    Object o = obj;
    Class<?> clazz = obj.getClass();
    Method method = null;
    try {
        for( String name : methods ) {
            method = clazz.getMethod( name, null );
            o = method.invoke( o, null );
            clazz = method.getReturnType();
        }
    } catch( NullPointerException e ) {
        System.err.println(clazz.getSimpleName()+"(null)."+method.getName());
        return false;
    } catch( NoSuchMethodException e ) {
        e.printStackTrace();
    } catch( SecurityException e ) {
        e.printStackTrace();
    } catch( IllegalAccessException e ) {
        e.printStackTrace();
    } catch( IllegalArgumentException e ) {
        e.printStackTrace();
    } catch( InvocationTargetException e ) {
        e.printStackTrace();
    }
    return true;
}

System.out.println(nullCheck(GraphicsEnvironment.getLocalGraphicsEnvironment(), "getDefaultScreenDevice", "getDisplayMode", "toString"));
System.out.println(nullCheck(GraphicsEnvironment.getLocalGraphicsEnvironment(), "getDefaultScreenDevice", "getFullScreenWindow", "doLayout"));

brings

true
false

'Window(null).doLayout'
oliholz
  • 7,447
  • 2
  • 43
  • 82
0

you can achieve this by using reflection, here is your method:

public boolean dynamicNullCheck(Object o, String path) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Object object= o;
    for (String element : path.split("\\."))
    {
        Field field = object.getClass().getDeclaredField(element);
        field.setAccessible(true);
        Object fieldVal = field.get(object);

        if (fieldVal!=null)
        {
            field.setAccessible(true);
            object = fieldVal;
        }
        else
        {
            return true;
        }


    }
    return false;


}

use it by giving your root element and path to each object, ie dynamicNullCheck(objA,"b.c.d")

user902383
  • 8,420
  • 8
  • 43
  • 63