Check if last getter in method chain is not null

前端 未结 3 715
春和景丽
春和景丽 2020-12-06 12:31

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()

相关标签:
3条回答
  • 2020-12-06 12:52

    As already stated, the true solution is refactoring.

    In the meantime, you could just wrap your first workaround in a function:

    static D getD(MyClass obj) {
    
        try {
            return obj.getA().getB().getC().getD();
        }
        catch (NullPointerException e) {
            return null; // Or even better, some default D
        }
    }
    

    At the caller site:

    D d = getD(obj);
    

    At least you don't have to trash the caller with try-catch blocks. You still need to handle the errors somehow, when some of the intermediate getX() call returns a null and so d becomes null. The best would be to return some default D in the wrapper function.


    I don't see how the two options you list at the end of your question would help if any of the intermediate getX() returns a null; you will get a NullPointerException.

    0 讨论(0)
  • 2020-12-06 12:55

    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.

    0 讨论(0)
  • 2020-12-06 13:08

    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

    0 讨论(0)
提交回复
热议问题