5 ms·
TL;DR You can call `Optional.get()` to deliberately circumvent the safety mechanisms of Optional. The author apparently concludes that since it does not solve
by w23j 11y ago
TL;DR
You can call `Optional.get()` to deliberately circumvent the safety mechanisms of Optional.
The author apparently concludes that since it does not solve ALL error cases it does not solve ANY error cases...
- Cthulhu_ 11y agoThe problem is that you don't get guarantees that something is not null; you can still do Optional<T> myOptional = null. Second, you're not required to handle the not-present case. Third, if you attempt to get the value of an optional (using .get()) when it is not present, you get an (unchecked, so no requirement to catch) exception - basically replacing NullPointerException with NoSuchElementException. The only value Optional has over regular values is that the developer has to assume the value can be missing - but the same was true for nullable properties.
- w23j 11y agoAt least one of the values of Optional is to communicate in the API that a value can be missing. The article mentions that: A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario." Making this clear to users of an API is something that nullable properties can not do. The user has to deliberately ignore the fact that the value might be missing by calling `.get()`. This looks like a advantage to me, so to say that Option does not solve ANYTHING seems incorrect. It certainly does not solve EVERYTHING.
- malka 11y ago> A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario." Well, that's basically the same thing with any nullable return then. Wether I return T or Optional<T>, there might be no record. Even worse, when I return T, you only have 2 cases : I return something, or I return null. With optional, you have 3 cases to check : I returned Something, I returned Optional.of(null), or I returned null.
- organsnyder 11y agoYou should never have to check that the Optional itself is null. While that is allowed by the language, it is such an obvious error that static analysis tools could easily detect it.
- MBCook 11y agoThen it shouldn't be allowed by the language, and that's the core issue. Until the compiler enforces that Optionals aren't null they're not fit for most purposes.
- w23j 11y agoI am not sure I understand. I guess you are either saying (A) to treat every return type as possibly null or (B) to use your judgment when doing null checks of return types. In case of (A): Do you want to write null-checks for methods like String.toUpperCase() or for user.getLastName()? That would lead to a lot of bloated, dead code. Also do you want to write error handling for all these cases you know can never happen? In case of (B): NullPointerExceptions are most likely when the user of an API did not expect he might get a null value. For instance user.getDepartment -> null. "What? An employee does not have to have a department?!" In this case you force users of an API to guess if they might reive a null return value. And they might guess wrong, which either leads to dead code or NPEs. Using Optional as a return type makes the difference explicit.
- MereInterest 11y agoI would say that every return type that can be NULL should be checked for being NULL. In C++, this is possible, because you most functions are return-by-value or return-by-reference. This leaves only return-by-pointer that need to be explicitly checked. In Java, all functions that do not return primitives are return-by-pointer, and are therefore nullable. This, as you mentioned, makes it infeasible to apply null-checks on every function return.
- craigching 11y ago
- jcrites 11y ago> Optional<T> myOptional = null That hasn't been a problem for me in practice. It's pretty clear that a reference to Optional should never be null. It can be statically or dynamically checked with @Nonnull or a precondition. > but the same was true for nullable properties. It's inconvenient to have to treat everything as possibly null. It's a lot nicer to create the convention, within one's codebase, that references are always nonnull and only Optional are nullable.
- gurkendoktor 11y ago> That hasn't been a problem for me in practice. It has for me. Functions have multiple return points, some of them returning "null". Lead developer insists we use Optional<> to clarify that these functions can return null. People go over the function, replacing each instance of "return null" with "return Optional.empty()", but forget some instances. Now we have Optionals that are sometimes null.
- RHSeeger 11y agoBut that's a bug in the library (or code you're calling into), not a bug in how you're using it. That's the main difference in my opinion. Optional allows the code to say "I never intend to return null, only an Optional that may be nothing". In theory, a library/module/whatever that's been converted to use Optional should not have any calls that do return null. In theory, its no different than a C API that can return a size or -1 for failure. Sure, it could return -2 because the language allows it, but you shouldn't need to check for that in your code that uses it.
- jcrites 11y agoIf you are in the midst of an upgrade like this, then you might want to program defensively. In this case I would do that by applying annotations like FindBugs' @CheckForNull or @Nonnull or @Nullable. Across a trust boundary like an interface, it's possible to establish a convention like: every reference shall have one of those. You might be able to write a CheckStyle rule that verifies that every reference either has an annotation or is an Optional. Last but not least, assertions can be tremendously useful. Add Objects.requireNonNull() checks liberally, especially anywhere you pass a reference from one place to another without using it. By applying these techniques you can quickly create a "demilitarized zone" for null, allowing you to use Optional confidently on the other side. Errors are caught quickly and locally by analysis and assertions. In a large codebase it's not an all at once upgrade, unless you refactor checked by static analysis, but you can be confident in the parts you've upgraded.
- AlisdairO 11y agoRight, but the difference in reality is that developers don't check every reference to see if it's null. The difference between a raw reference and optional is that with optional the author of the interface has explicitly signalled 'you really ought to check this'. Optional provides the ability to work with better conventions. Sure, this doesn't live up to the actual guarantees provided by other languages, but that's not the same as being useless.
- pjmlp 11y agoYou can do it today, but that won't work in Java 10 with value types. Optional is planned to become a value type.
- nrinaudo 11y agoI disagree with some of your points. The fact that you can get a null instance of Optional is not Java specific - Scala has the same issue, for example. Saying that Optional does not sort any problem because there is no way to enforce it cannot be null is just wrong - it sorts plenty of problems, just not all of them (you didn't mention the case of an optional that contains null, which is unpleasant as well). You can indeed call .get - so can you in Scala (.get) or Haskell (fromJust) with exactly the same semantics. What do you propose for the case where you know that there is a value in there but can't make the type system aware of that fact (you've called isPresent beforehand)? pattern matching and fail in the empty case? How is that different from calling get? Is it because of the fact that the exception is unchecked? In that case, why not throw a more specific, checked exception through orElseGet? And if you know that there is data to be had, isn't that exactly why we have unchecked exceptions in the first place? You absolutely are required to handle the not-present case - you can't treat an Optional<T> an a T, and someone will need to decide what to do at some point. Either the caller (ie you return an Optional yourself after mapping into it) or you. There's a wide range of ways you can do that, one of which being "I want to fail if there is no data" - that's either .get if you don't need a checked exception or .orElseGet if you need something more constrained. You can also decide to use a default value, or o different code path entirely... Optional has issues - it can contain reference to a mutable variable, for exemple, or you might find yourself with a null optional or an optional that contains null. It's not perfect. It's also a lot better than the alternative, null, as it lets you communicate some of your constraints to the compiler and allow it to catch certain kinds of errors at compile-time rather than at runtime. Rather like the rest of the Java type system, in fact - it's far from perfect, it doesn't catch all type errors at compile time, but it's (arguably) better than a fully dynamic one.
- ralmeida 11y agoDefinitely. For me, the main use case of Optional is to provide a way for programmers to express the semantic fact that "there is no such object" without resorting to null. Doing this leads to checking if (obj == null) for dealing with the semantic case that the object is not present, but other kinds of failure may cause obj to be null, but should be treated differently (for being a lower-level issue, for example). So, Optional<T> is basically a way to differentiate between different types of nullity.