And in those cases where you still need specific behaviour based on which object is null, you can still use the . operator with traditional null pointer checks.
var = foo()?.bar?.bing()
if(foo==null){...}
instead of putting a null check between every call. In many cases null is used to indicate that a computation failed. If you are doing a chain of computations, there is often not a reason you need or want to do a check between every computation, instead of having a single handler at the end for if any of them fail.This pattern comes up fairly often in Haskell, which accomplishes it with the Maybe monad.
It's not always so cut and dry, and there are situations where this is a very valuable tool. I just feel that down the road if you feel like there is a valid reason for refactoring object hierarchy that you'll potentially be doing yourself (or those that follow) a disservice in the long run.
Quite often, you simply want person.address.street.number, and if it doesn't exist, you simply go on without it, and it doesn't matter what the exact reason is why it doesn't exist. This is an extremely common and practical pattern, and it's hindered by layers of null pointer checks.