Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if last getter in method chain is not null

In code we have got a lot of chain methods, for example obj.getA().getB().getC().getD(). I want to create helper class which will check if method getD() isn't null, but before that I need to check all previous getters. I can do it in this way:

try {
    obj.getA().getB().getC().getD();
}
catch (NullPointerException e) {
    // some getter is null
}

or (which is "silly")

if (obj!null && obj.getA()!=null && obj.getA().getB()!=null && ...) {
    obj.getA().getB().getC().getD();
}
else {
    // some getter is null
}

I don't want to check it every time using try{} catch() in my code. What is the best solution for this purpose?

I think that the best will be:

  1. obj.getA().getB().getC().getD().isNull() - for this purpose I will need to change all of my getters, for example implement some interface which contains isNull() method.
  2. NullObjectHelper.isNull(obj.getA().getB().getC().getD()); - this will be the best (I think so) but how to implement this?
like image 614
pepuch Avatar asked Oct 28 '13 08:10

pepuch


People also ask

How do you check if a return is NULL?

The is_null() function checks whether a variable is NULL or not. This function returns true (1) if the variable is NULL, otherwise it returns false/nothing.

IS NOT NULL function in Java?

notNull() is a static method of the Validate class that is used to check whether the passed object is null or not. If the passed object is null , then the method raises an exception with a formatted message. If the passed object is not null , then the method returns the input as it is.

Can a getter return NULL?

If your getter must always return an object that works with chained Linq operators, you can never return a null. If your getter must always return what you set, then you cannot coerce it to another object.

How do I avoid multiple nulls in Java 8?

We can get rid of all those null checks by utilizing the Java 8 Optional type. The method map accepts a lambda expression of type Function and automatically wraps each function result into an Optional . That enables us to pipe multiple map operations in a row. Null checks are automatically handled under the hood.


2 Answers

As of Java 8 you can use methods like Optional.isPresent and Optional.orElse to handle null in getter chains:

boolean dNotNull = Optional.ofNullable(obj)
              .map(Obj::getA)
              .map(A::getB)
              .map(B::getC)
              .map(C::getD)
              .isPresent();

While this is preferable to catching NullPointerException the downside of this approach is the object allocations for Optional instances.

It is possible to write your own static methods that perform similar operations without this overhead:

boolean dNotNull = Nulls.isNotNull(obj, Obj::getA, A::getB, B::getC, C::getD);

For a sample implementation, see the Nullifier type here.

No approach is likely to have greater runtime efficiency than nested if-not-null checks.

like image 55
McDowell Avatar answered Sep 30 '22 06:09

McDowell


You can achieve the desired result with Option pattern. This enforces you to change a method signature, but basically if your method returns some type T, it guarantees it has some non-null value, and if it returnsOption<T> it means it either has value T, or null.

Java 7 had some feature called null safety, but it was removed from the final release. You could do:

obj?.getA()?.getB()?.getC()?.getD()

Moreover, Java 8 will add a feature called Optional so you would do it safely.

In fact, if you really want to use that now, try Null Object pattern. It means that instead of returning plain null you can return some sort of default value, which won't trigger NullPointerException. Though, you need add some changes to your getters

class Object {
   A getA() {
     // ...
     return a == null ? A.NULL : a;
   }
}

class A {
   static A NULL = new A(); // some default behaviour
   B getB() {
     if (this == NULL) return B.NULL;
     // ...
     return b == null ? B.NULL : b;
   }
}

EDIT: If you want utility to do it you can wrap it in some functional interface and then call it.

static boolean isNullResult(Callable call) throws Exception {
    try {
        return call.call() == null;
    } catch (NullPointerException npe) {
        return true;
    }
}

Usage will be the following:

isNullResult(new Callable<Integer>() {
    @Override
    public Integer call() throws Exception {
        return new A().getB().getC().getInt();
    }
});

It won't require you to change existing functionality

like image 20
mishadoff Avatar answered Sep 30 '22 06:09

mishadoff