Lately I’ve seen code bases where the Java devs don’t return empty arrays or collections but return null instead. Of course they have to test for null in their calling code. I suggested to return empty collections and objects implementing the NullObject pattern. I think this will make the code more readable, simpler and more secure, but I was answered with skepticism.
Interestingly I agree w/ a preference for empty semantics over null semantics, but NOT for the reason "avoid NPE". Rather, I think minimizing branching/forking in the code logic is how complexity is reduced.
For this same reason I don't care for NullObject/Maybe/Optional type approaches which simply do not change the branching forking in your code:
if (val == null) { ...logic... }
This branching here ^ is not improved at all by a different syntactical representation:
((Optional) val).ifNull(v -> ...logic...)
You are still branching, so in my opinion you've made no substantial improvement here. (I can already hear the "but, but..."s.
I'm dealing with an old code base in which methods tend to process exceptions by catching, logging and returning a null. The dev that wrote this code treated exceptions more like a rare-occurring annoyance rather than a signal for error, thus none of the calling methods had null check branching implemented. The amount of NPEs I had to fix in the past year is astounding.
Optional to me is a large leap forward. That being said, I also don't like its verbosity and wish for it to be improved somehow.