5

We have all seen that kind of code

if (myObject!= null 
  && myObject.mySubObject() != null
  && myObject.mySubObject().getSpecificValue() != null
  && !myObject.mySubObject().getSpecificValue().isEmpty()
) {
     ......
}

How could I write this the clean way ?

Seb
  • 3,602
  • 8
  • 36
  • 52
  • 4
    Unfortunately, this **is** the "clean way". Welcome to Java! – Jordan Jan 29 '20 at 15:58
  • 2
    [Optionals](https://www.tutorialspoint.com/java8/java8_optional_class.htm) are an alternative, but they need training to handle right, otherwise they are as messy as this. However, as @Jordan already noticed, this kinda is the way you do it in java... – gkhaos Jan 29 '20 at 15:59
  • 1
    Does this answer your question? [Java "?" Operator for checking null - What is it? (Not Ternary!)](https://stackoverflow.com/questions/4390141/java-operator-for-checking-null-what-is-it-not-ternary) – Orace Jan 29 '20 at 16:00
  • What if `mySubObject` is not pure and or time consuming ? – Orace Jan 29 '20 at 16:01
  • 2
    Does this answer your question? https://stackoverflow.com/questions/27074474/is-there-a-operator-for-java-to-perform-null-pointer-checking – Orace Jan 29 '20 at 16:04
  • 1
    Agreed with @Jordan, also NPE can come handy in cases where the target object are too deep level. just Use try catch block for `NullPointerException` If in `catch`, treat as `else`, otherwise, proceed using the target object in `try block` as `if block`. It's not worth mentioning this as answer, so putting in comments only `try { Object o = myObject.mySubObject().getSpecificValue(); // use o further } catch(NullPointerException npe){ // else logic can come here; }` – miiiii Jan 29 '20 at 16:06
  • `Optional` is the idiomatic way to go here, in modern Java. – Zabuzard Jan 29 '20 at 16:12
  • @Orace I hoped a nicest way would exist, what do you mean by pure / time consuming ? – Seb Jan 29 '20 at 16:19
  • @miiiii Don’t ever catch NullPointerException, ever, under any circumstances. NullPointerException exists to expose programmer errors. Catching it prevents mistakes from being detected. – VGR Jan 29 '20 at 17:29
  • @VGR I know. that's why said in comments that it's not good to use NPE hence not considering it as answer. Just mentioned as work around (but very bad alternative). – miiiii Jan 29 '20 at 18:55

2 Answers2

6

You can do chaining with Optional:

Optional.ofNullable(myObject)
  .map(o -> o.mySubObject())
  .map(so -> so.getSpecificValue())
  .map(sv -> sv.isEmpty())
  .orElse(false)

Or with method references even shorter (does the same):

Optional.ofNullable(myObject)
  .map(Foo::mySubObject)
  .map(Bar::getSpecificValue)
  .map(Baz::isEmpty)
  .orElse(false)

where Foo, Bar and Baz are the names of the respective classes.

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Iskuskov Alexander
  • 4,077
  • 3
  • 23
  • 38
  • 1
    Neat way of using Optionals! – gkhaos Jan 29 '20 at 16:06
  • 1
    You can also use method references. – Zabuzard Jan 29 '20 at 16:09
  • Just wandering, won't it create NPE on `so.getSpecificValue()` if `o.mySubObject()` returned `null`. – miiiii Jan 29 '20 at 16:10
  • 1
    @miiiii No, because `Optional#map` will only continue if the Optional is present, i.e. not empty. So this is ensured by starting with `Optional.ofNullable`. That is the whole point of the `map` method in `Optional`. – Zabuzard Jan 29 '20 at 16:11
  • I like the way but it's still very long and not "clear", I mean it's not obvious that you're trying to check specificValue existence – Seb Jan 29 '20 at 16:14
  • 1
    @Zabuza just wrote a code in IDE and ran as I was not convinced yet. But You're right. It works as expected. I wasn't aware of this. Thanks. I wish could give upvote for your explanation. :) – miiiii Jan 29 '20 at 16:22
  • That is probably the best general purpose solution for this situation that exists in Java. I personally like it, have a better suggestion? What kind of syntax would you like to have? I can not really come up with something more compact/clean. – Zabuzard Jan 29 '20 at 16:22
  • I mean, you could always just create a little helper method to do exactly that `private static boolean doesBazExist(Foo foo)` if you really have to do this more than once. – Zabuzard Jan 29 '20 at 16:24
  • 1
    Yup. Agreed. I must say, the way Java has implemented functional programming paradigm is much nicer than traditional Functional Languages I've explored so far. Nice to talk to you. :) – miiiii Jan 29 '20 at 16:25
  • a scope?.subobject?.specificValue would be nice, what do you think ? – Seb Jan 29 '20 at 16:34
  • I see. That would be a feature integrated into the language level. Like in languages like Kotlin. So far Java does not offer anything in that direction, on a language level. – Zabuzard Jan 29 '20 at 16:35
1

If you are using someone else's code then you're really stuck handling for a possible null. On the other hand, if you have control over the code base then never return a null object, and make that a rule across your entire application.

This may sound bad at first but I have developed several enterprise-level applications and this is a very effective way to make the code consistent and much more readable.

So, now, this

if (myString != null && !myString.isEmpty()) {

becomes simply

if (!myString.isEmpty()) {

In lue of that option use the new Optional feature in J8 as it is intended for that purpose.

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
AstarAndy
  • 121
  • 1
  • 8
  • This is the correct answer: Do not treat null as a normal value. Most of the time, null is not needed in complex objects, especially collection properties. – VGR Jan 29 '20 at 17:32