try..catch VS long if() [duplicate]

2019-07-19 22:24发布

This question already has an answer here:

I have a complex model structure in my project.
Sometimes I have to get a deep placed value from it. It looks like following:

something.getSomethongElse().getSecondSomething().getThirdSomething().getFourthSomething();

The problem is that each of those methods could return null, and I will get NullPointerException in case if it does.

What I want to know is should I write long if like

if(something != null && something.getSomethongElse() != null && something..getSomethongElse().getSecondSomething() != null && something.getSomethongElse().getSecondSomething().getThirdSomething() != null && omething.getSomethongElse().getSecondSomething().getThirdSomething().getFourthSomething() != null) {
    //process getFourthSomething result.
}

Or it is OK just to use try..catch like following:

SomethingFourth fourth = null;

try {
    fourth = something.getSomethongElse().getSecondSomething().getThirdSomething().getFourthSomething();
} catch (NullPointerException e) { }

if(fourth != null) {
    ///work with fourth
}

I know that NPE is a thing to be avoided, but isn't it overhead to avoid it in my case?

1条回答
倾城 Initia
2楼-- · 2019-07-19 22:52

If you can refactor the code and make each method return Optional. It will be possible to avoid null checks and try ... catch.

Optional<Result> result = something.getSomethingElse()
.flatMap(e -> e.getSecondSomething())
.flatMap(x -> x.getThirdSomething())
.flatMap(e -> e.getFourthSomething());
// at the end to check if result is present
result.ifPresent(..some_logic_here..); // or result.orElse(...);

so getSomethingElse() returns Optional<SomethingElse>, getThirdSomething() - Optional<ThirdSomething> and so on. We have to use here flatMap(Function<? super T,Optional<U>> mapper) because if the provided mapper is one whose result is already an Optional, and if invoked, flatMap does not wrap it with an additional Optional. In other words if map on map(e -> e.getSecondSomething()) the result type will be Optional<Optional<SecondSomething>> and we will have to do unnecessary get() call - map(...).get().map(...).

I hope this helps.

UPDATED You can do the same thing using method references.

Optional<Result> result = something.getSomethongElse()
            .flatMap(SomethongElse::getSecondSomething)
            .flatMap(SecondSomething::getThirdSomething)
            .flatMap(ThirdSomething::getFourthSomething);
查看更多
登录 后发表回答