4 ms·
Adding my voice to the din of people noting how far afield of the point the author is: You should almost never call .get(), except in cases where the code path
by ubertaco 11y ago
Adding my voice to the din of people noting how far afield of the point the author is:
You should almost never call .get(), except in cases where the code path does not allow an empty optional.
Even so, calling .get() on an empty optional is better than handing nulls around. A null may -- by chance, really -- make it several lines down the code, so that the stack trace points you much later in the code than where the null originated. Calling .get() on an empty optional immediately throws a NoSuchElementException, pointing you directly to the line where the optional was empty where it shouldn't have been.
Consider this code:
User user = getUser();
// other stuff here
// ...
// ...
String userSummary = formatUserSummary(user);
// ...
// ...
where
public String formatUserSummary(User user){
return "Franchise Location: " +
user.getFranchise().getLocation().getName() +
" Username: " +
user.getUsername();
}
An NPE occurs inside of formatUserSummary. Where did the null come from? Is the user's Franchise null? Maybe the Franchise's Location? Or is it the User that's null?
If you instead took an Optional<User>, even if you just immediately unwrapped it with .get(), you'd at least get an error that unambiguously told you that it was the user that was missing.
- ucho 11y ago> Where did the null come from? A bit offtopic but SAP JVM puts that info in NPE error message[1], I don't know why others implementations don't, maybe it is incurring too large overhead? [1] it is something like "Attempted to call getLocation() on Franchise object returned from getFranchise() but it was null"
- Ygor 11y agoInteresting, first time I heard SAP has a JVM implementation. https://scn.sap.com/people/desiree.matas/blog/2011/12/07/sapjvm-overview https://scn.sap.com/people/desiree.matas/blog/2011/12/07/sap... Here is a presentation with some interesting points, wonder if anyone has any real-life experiences? https://www.youtube.com/watch?v=arryAs9lqfE https://www.youtube.com/watch?v=arryAs9lqfE
- kllrnohj 11y agoART on Android does this as well.
- jtheory 11y agoNulls can be particularly pernicious in Java because of auto-unboxing. E.g., imagine you got a NPE from this: String summary = getUserSummary( user.getId() ); ...you'd think "user" must be null, right? But it's quite possible that user.id is a Long, the current value is null, and getUserSummary() requires a long primitive argument. This compiles just fine, and at runtime the Long object will be auto-unboxed to a primitive long... unless it's null. Surprise! But things like Optional do help; doing a code review for the things that may be null will fix these kinds of mismatches (and you'll avoid relying on auto-unboxing). The above code is broken -- either user.getId() can never be null (in which case it should be a primitive already) or it might sometime be null, in which case this code must not allow auto-unboxing.
- jdmichal 11y agoI had a fun one with this once. It looked something like this, using your `user.getId` method: int userId = p ? 0 : user.getId(); We spent a few hours staring at this trying to figure out why there was a `NullPointerException` on a line dealing with `int` values. Eventually realized that `thing` was really an `Integer`, causing the entire trinary to be an `Integer`, which was then being unboxed to an `int`.