7 ms·
The author is missing the point. The fact that Optional can result in a nullpointer doesn't mean you should use in the same manner as null-checks. You shouldn'
by Kwastie 11y ago
The author is missing the point. The fact that Optional can result in a nullpointer doesn't mean you should use in the same manner as null-checks.
You shouldn't replace:
if(x == null)
{
y = x.doSomething();
}
with
if(optionalX.isPresent())
{
y = x.doSomething();
}
You should replace it with:
y = Optional.ofNullable(x)
.map(ClassX::doSomething)
.orElse(null);
- danieldk 11y agoThe author is missing the point. Is he? The point is that in Java you are still able to treat x unsafely, while languages with stronger typing do not. E.g. in Haskell, if a function returns a Maybe a, it will always be a Just a or Nothing value. Moreover, such languages allow you to make non-exhaustive matching against all constructors a compiler error. tl;dr: Haskell, Rust, et al. put the burden on the compiler. Java puts the burden to ensure safety on the programmer. (As can be witnessed in your snippet.)
- pron 11y agoAs of Java 8, Java has pluggable type systems[1], some of them are more advanced than what Haskell provides (like true intersection unit types), some effect types (locks etc.) and more. So Java puts the burden on some very advanced -- but optional -- type systems. [1]: http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html http://types.cs.washington.edu/checker-framework/current/che...
- coldtea 11y ago>Java puts the burden to ensure safety on the programmer. (As can be witnessed in your snippet.) And that's OK too, if less than ideal. The Optional type serves as a reminder to use it differently.
- krisdol 11y ago>tl;dr: Haskell, Rust, et al. put the burden on the compiler. Java puts the burden to ensure safety on the programmer. (As can be witnessed in your snippet.) Actually, (much to my disappointment as I'm just learning rust) you can just take an Option or Result and .unwrap() and the compiler won't complain at you for not checking it. For such a "safe" strongly-typed language, I'm surprised that so much new rust code does this when: * the developer believes the Option/Result can never be None/Err (oh come on, just wait until you refactor your code a bit one day and miss a spot) * the code is example code (I've had little luck finding "good" examples sprinkled about github) * the developer is lazy (see above) Allowing unsafe unwraps defeats a core purpose of rust, and the unwrap method shouldn't even exist in the API.
- danieldk 11y agoAllowing unsafe unwraps defeats a core purpose of rust, Definitely, but you can also still do this in Haskell (fromJust). But it's better than nullable types since you explicitly have call an unsafe method. (Assuming that you have set non-exhaustive pattern matching to be a warning/error.)
- steveklabnik 11y agounwrap() is not unsafe in Rust, and I don't think Haskell has anything similar?
- danieldk 11y agoSorry for the confusion! I meant 'unsafe' as in partial (not safe for all inputs). Not as in Rust's unsafe keyword.
- steveklabnik 11y agoAh, right. It's really important in the context of Rust. :) People sometimes claim that unwrap() violates memory safety, which isn't true.
- 11y ago
- blktiger 11y agoThe point of the new Optional type in Java isn't to prevent NPEs, it's to make using the new Streams API cleaner. Since you can now flow through optional values in a stream you can ignore whether the stream contains optionals or not and only deal with them at the end. It's certainly possible that in a future version of Java the optional type might be paired with something like pattern matching to prevent NPEs with some syntax sugar, but that's not the reason that the Optional type exists today.
- pcote 11y agoNot entirely true from what little I know about Haskell. Haskell might put MORE of the burden on the compiler but it doesn't put ALL of it there. The following generates a runtime exception. (not a compile time type error) head []
- michaelfeathers 11y agoClose, but not quite there. You should leap over tall buildings to make sure that you never have to set y to null. In my code, I'm only dealing with null if a API gives me one. At that point, I take some sort of action to make absolutely sure I'm not passing it along to anyone else. This means using exceptions, the null object pattern, or Optional without a need to dereference. The goal is to prevent a proliferation of references that could be null and therefore have to be checked.
- tel 11y agoOf course, ClassX::doSomething must still be at least in principle prepared to handle nulls.
- eweise 11y agoI agree. Having programmed in java for the past 15 years, I can attest that NullPointerExceptions are a constant source of errors. The main benefit I've experienced with Optional is that it documents the fact that a method might return a null value. Without this, the client has to guess whether or not to add defensive null checks.
- plonh 11y ago@Nullable already does that.
- Aardwolf 11y agoImho the "you should replace it with" is the least readable code snippet of all 3. (Also I assume the first is intended to be x != null)