(a) in a case where failure is supposed to be possible, you are strongly pushed to check for null when it first comes up, rather than just ferrying around the returned object and perhaps getting a NullPointerException five levels into a subsequent function call;
(b) in a case where failure is not supposed to be possible, which is probably the majority of cases where NullPointerExceptions come up in practice (since failure is more commonly represented by exceptions or error codes than just null), you have the type system verifying that there is no path through your code that accidentally fails to initialize a variable or otherwise introduces a null.
edit: Of course, initialization is not always predictable enough for the type system to verify it, but here functional-ish type systems can help: if your class data looks like "bool connected; Socket socket;", it's possible that you could accidentally end up with connected == true but socket == null, but if you write it as (pseudocode) "state : data Disconnected | Connected (socket : Socket)", with Socket non-nullable, you're assured that it's impossible.
those are both big advantages, but neither of them make dealing with the errors easier or more predictable as far as I can tell. it would definitely constrain the locations in your code where there could be surprise though and maybe that's enough?
(a) in a case where failure is supposed to be possible, you are strongly pushed to check for null when it first comes up, rather than just ferrying around the returned object and perhaps getting a NullPointerException five levels into a subsequent function call;
(b) in a case where failure is not supposed to be possible, which is probably the majority of cases where NullPointerExceptions come up in practice (since failure is more commonly represented by exceptions or error codes than just null), you have the type system verifying that there is no path through your code that accidentally fails to initialize a variable or otherwise introduces a null.
edit: Of course, initialization is not always predictable enough for the type system to verify it, but here functional-ish type systems can help: if your class data looks like "bool connected; Socket socket;", it's possible that you could accidentally end up with connected == true but socket == null, but if you write it as (pseudocode) "state : data Disconnected | Connected (socket : Socket)", with Socket non-nullable, you're assured that it's impossible.