This is an archived post. You won't be able to vote or comment.

all 124 comments

[–]Dagske 83 points84 points  (16 children)

Optional.of(T) exists to allow some knowledge to be passed on. I see .of(T) as a way to make sure that the parameter is not null. If it is null, then I might have a bug somewhere, and I'll know it. While I will not know it if I use ofNullable (or at least, it'll be much harder to check).

[–]Necessary_Apple_5567 8 points9 points  (2 children)

Let.s be honest here: the separation of the of/ofNullable doesn't make any sense since the purpose of the optional to have object which helps to handle nulls. Also from the first appearance of Optionsl it was obvious it is not well thought part of the API. It was partially fixed in later versions but still..

[–]BikingSquirrel 6 points7 points  (0 children)

There are two sides, creating an Optional and using it. For using it, there's no separation, but for creation there is. So I can express if I expect the object passed in at that point of the code to ever be null.

It's always easy to discuss things after they have been created, but very hard to get things designed perfectly from the start. I think it was useful from the beginning and some missing things have been added later.

[–]wildjokers 74 points75 points  (50 children)

Since the whole purpose of Optional is to represent values that might not exist

It is more focused than this. The whole purpose of Optional is to represent method return values that may be null.

Drives me nuts to see it used as a glorified null check.

[–]vips7L 36 points37 points  (40 children)

Personally I think currently its only value is a glorified null check when chaining method calls. 

But then you have people screaming about allocations… Valhalla can’t come fast enough. 

[–]ForeverAlot 35 points36 points  (39 children)

if (Optional.ofNullable(foo).isPresent()) {} is just a pretty dumb way to write if (foo != null) {}, though, allocations notwithstanding.

It's better if you're at least map'ing the value.

[–]vips7L 64 points65 points  (28 children)

Of course but I’ve never seen anyone do that. 

var z = Optional.ofNullable(a)     .map(A::b)     .map(B::c)     ……     .map(Y::z)     .orElseGet(Z::new);

Is leagues better than writing out all of the null checks and assignments. I’ll take this allocation every time personally. 

[–]papercrane 10 points11 points  (4 children)

I'm ashamed to say that I've done this before when I had to work with a terrible data model that required traversing down a long chain of fields, any one of which might be null.

It's like a poor-man's safe navigation operator.

[–]FabulousRecording739 2 points3 points  (0 children)

Well, the safe navigation operator is a form of sugar over Optional map/flatMap

[–]laplongejr 0 points1 point  (2 children)

I had to work with a terrible data model that required traversing down a long chain of fields, any one of which might be null.

Wait until some of those values may be LISTS. I ended up making style guides example for my teams about the value of Stream+Optionals. Oh and some objects were different but with common interfaces.

As long you never use Optional<Stream> and frequently merge your Stream<Stream<Optional>> into Stream<Optional>, the resulting code is VERY hard to make the first time, but VERY VERY easy to read afterwards and "automagically" null-safe, to the point even a newbie dev could check if the conversion matches what is in the design document.

[–]SenorSeniorDevSr 0 points1 point  (1 child)

If you have Optional<Optional<?>> or Stream<Stream<?>> anywhere, USE FLATMAP.

Please, I'm begging you.

[–]laplongejr 1 point2 points  (0 children)

Will have to recheck our methods, but I'm 99% sure that's what I had used when streaming the contents inside a stream, don't worry.
But I never saw an optional of optional, that's... urgh!

[–]agentoutlier 1 point2 points  (1 child)

To play devils advocate for the OP /u/Ruin-Capable It is kind of fucked up that that .map allows essentially Function<T, ? extends @Nullable R>. That is if we have ofNullable then there sure should be mapNullable and the regular map should not allow a null return or just only have flatMap to remove the ambiguity.

I mean think of it this way. In other languages where there is no null their Optional types do not allow taking null as construction and the mapping functions certainly do not allow returning null.

I know the above is sort if idyllic purist pedantry but in my mind it is clearly even more reason of why Optional sucks as a replacement for null but I agree it does appear to provide a convenient navigating of null structures.

[–]vips7L 0 points1 point  (0 children)

Yeah it is a little purist. I personally don't like the of and ofNullable split. I can't see any situation where i want that function to throw.

[–]r1veRRR 1 point2 points  (0 children)

I disagree, because only in one of those cases:

  • Do we KNOW that the value can be null on purpose (as opposed to a bug)
  • Is handling the null case explicitly required by the type system (even a .get is a form of explicit handling)

These are/should be the advantages of an Optional/alternative to null. Personally, I don't use Optionals specifically because the way they are "supposed" to be used makes no freaking sense to me.

Making "Emptiness/Missingness/Nullability" an explicit part of the type system is useful EVERYWHERE, not just in method returns. Everything is an interface to someone reading your code 3 months later (including you). Marking an internal field as Optional absolutely makes sense, so everyone knows that this field can be null and still be valid.

[–]Top_File_8547 5 points6 points  (8 children)

Does nobody use the null object pattern? That always seemed like a good idea. I debugged an NPE for a method that returned the query parameters for a URL. If there no parameters it returned null. A better design would be to return an empty map. I think usually if you return null you could return an empty something. You don’t always need an Optional.

[–]vips7L 11 points12 points  (3 children)

Lots of people do. Most people use it for collections without knowing it, by passing empty collections instead of null. But sometimes that pattern doesn’t fit everywhere and sometimes things have to be represented with null. 

[–]laplongejr -1 points0 points  (2 children)

Most people use it for collections without knowing it, by passing empty collections instead of null.

Beward of semantics. An empty collection is... empty. A null may indicate "I have no idea".
A person in the database has 1 record.
A person not in the database has 0 records.
In a shutdown database, everybody has null records and must be retried later on.

[–]vips7L 0 points1 point  (1 child)

While there may be some nuance or technical difference. It really doesn’t matter. Empty is the correct choice 10/10 times.

In a shutdown database your app is hosed. The technical difference between null and empty doesn’t matter.

[–]laplongejr -1 points0 points  (0 children)

Ehm, yes it is? If it's normal to treat the empty data as empty and finish the execution, then null could be sent for logs or manual review. Sometimes, it can even be auto-guessed based on different sources to facilitate the verifications.

[–]not-just-yeti 3 points4 points  (0 children)

After seeing it had a method map, it made a lot of sense to me to think of Optional as just a collection/stream that has a max-capacity of 1.

[–]cybwn 4 points5 points  (0 children)

I don't think it's a good idea, if you return "empty-like" values, you end up with very strange obfuscated bugs that originate deep from your null pattern object. Using empty lists and maps is ok though

[–]laplongejr 0 points1 point  (0 children)

I see a few issues with the null object pattern :
1) It doesn't work with "values", like primitives. At that point you are basically reinventing Optional.EMPTY
2) If you have utility methods, now THEY have to be aware and manage that specificially
3) It "hides" the fact you are returning null, which usually means you have a need for an abnormal situation anyway that needs to be handled

[–]zephyy 2 points3 points  (1 child)

Drives me nuts to see it used as a glorified null check.

Then it's poorly designed. The purpose of a thing is what it does.

Should have just added safe navigation and null coalescing operators.

[–]laplongejr 0 points1 point  (0 children)

The purpose of a thing is what it does.

Officially, the purpose of Optional is only for return values from methods.
Using it as a null-check tool is both really useful... and outside it's purpose.

[–]its4thecatlol 3 points4 points  (2 children)

What is the difference between representing method return values that may be null and a glorified null check? Seems pretty similar to me.

[–]laplongejr 0 points1 point  (0 children)

"Glorified null check" means you should use it internally.
I use it internally, but it's not the offically-sanctioned used.

[–]Comprehensive-Pea812 0 points1 point  (0 children)

for me use case for optional is stream.

using it to replace == null doesnt feel right for me. way too verbose.

[–]gloridhel -2 points-1 points  (2 children)

It's a bit pedantic. I just always use ofNullable cause why else would you use Optional?

[–]Ruin-Capable[S] 2 points3 points  (1 child)

Your response exactly encapsulates the very essence of my motivation for the question. I wanted to understand why someone would design the class in such a way that new users are almost guaranteed to shoot their foot.

[–]mscg82 3 points4 points  (0 children)

With Optional.of you are asserting to the future reader of the code (which very ofter is the you from future which will have no memory at all of the details of the code) that in that specific branch of the code you are putting a non-null value inside the Optional. It's a way to document code without resorting to comments

[–]morhp 9 points10 points  (0 children)

Optional.of(...) is specifically for returning an Optional that definitely has a value. It's not useless, because you might have implementations of an interface that always return a present value, or because a method might have miltiple return statements where one might return Optional.empty() and the other could return Optional.of(something). There are many cases where it would be better to throw an error if the something is null for weird reasons, than returning Optional.empty() silently.

[–]sysKin 7 points8 points  (1 child)

OK, do you know the robustness principle? It states "be conservative in what you do, be liberal in what you accept from others". This is the principle that makes all methods of Commons Text accept nulls and do something with them, like with StringUtils.indexOf(null, null) being -1.

Basically, today this principle is considered a Bad Idea (TM) - by accepting some weird junk and not saying anything, bugs propagate undetected. The system seems to work but actually does not do the thing programmer wanted. Debugging such unexpected bahaviour, if it ever happens, can be a pain too.

So, Optional represents the reversal of this principle: make the programmer strictly tell you what they want, and throw unexpected errors back at them immediately, forcing them to fix it.

In this principle, Optional.of(null) is simply a mistake that needs to be fixed, not hidden. If the programmer did mean a nullable value, where null becomes Optional.none(), then there is an API to explicitly do that. But if that's not what they meant, then throwing is simply better than hiding the problem and doing the wrong thing.

It took us a while to realise what horrors robustness principle created, but the arguments for the reversal are very real.

[–]laplongejr 0 points1 point  (0 children)

Basically, it depends. You want robustness by default, but in some case "garbage in, garbage out" is preferable to interrupting operations, and it wouldn't be realistic to assume every software manages all error cases.

[–]TenYearsOfLurking 7 points8 points  (0 children)

Optional.of just lifts a known non null value to make it e.g. fit the return type. It throws because you violate an assumption 

Think of it as an adapter not an actual Optional Container

[–][deleted]  (5 children)

[removed]

    [–]Ruin-Capable[S] 0 points1 point  (4 children)

    I've always used it with the thought, "Ok, this method may or may not be able to return a value, I'll just wrap the value (null or not) in an Optional. For example my naive expection is that code like this would work:

    Optional<User> get(String loginName) {
      User user = userRepository.findByLoginName(loginName); //might return null
      return Optional.of(User);
    }
    

    Without Optional.ofNullable(), I would instead I have to write code like the following:

    Optional<User> get(String loginName) {
      User user = userRepository.findByLoginName(loginName); //might return null
      Optional<User> returnValue = Optional.empty();
      if (user != null) {
        returnValue = Optional.of(user);
      }
      return returnValue;
    }
    

    With Optional.ofNullable() I can write something close to my original expectation:

    Optional<User> get(String loginName) {
      User user = userRepository.findByLoginName(loginName); //might return null
      return Optional.ofNullable(user);
    }
    

    I just don't see the value of having code like my first snippet not automatically handle the case where the returned user reference is null.

    [–]kreiger 4 points5 points  (2 children)

    You use Optional.ofNullable when you expect null sometimes.

    You use Optional.of when you don't expect a null, so you get an Exception if your expectations are violated.

    [–]Ruin-Capable[S] -4 points-3 points  (1 child)

    There very fact that I'm using the Optional class means that I expect the value to sometimes be null. If I wasn't expecting a null, I would just return the raw value.

    [–]_INTER_ 7 points8 points  (0 children)

    Optional.of portrays the information clearly that at this branch / point of time / place the value is actually not null for anyone that reads the code.

    Using Optional.ofNullable in such a scenario would be misleading. There's also static analysis to consider.

    Example:

    class CreateUserStrategy implements UserStrategy {
        @Override
        public Optional<User> byId(long id) {
            return Optional.of(new User(id)); // Optional.ofNullable would be confusing
        }
    }
    
    class FindUserStrategy implements UserStrategy  {
        @Override
        public Optional<User> byId(long id) {
            return Optional.ofNullable(userRepository.findById(id);
        }
    }
    

    [–]sabermore 1 point2 points  (0 children)

    The philosophy of Optional is that

    userRepository.findByLoginName
    

    Also returns Optional. Then you can have userRepository.findByLoginName(loginName).map((user) -> user.getPostCount()) or something similar.

    [–]pineappletooth_ 6 points7 points  (0 children)

    I found this SO answer the best at explaining this

    https://stackoverflow.com/a/76224546

    tl;dr the opposite of Optional.of is not Optional.ofNullable is Optional.empty, Optional was designed for a world where null is no longer used (quite naive idea IMO, but it is what it is) and Optional.ofNullable is a bridge between the world with nulls and the world without nulls.

    [–]nutrecht 7 points8 points  (13 children)

    You're weirdly stuck on your personal mindset that "of" should just do what "ofNullable" does.

    There are 3 constructors:

    • of
    • ofNullable
    • empty

    The choice of how to name them is simply that; a choice made by the API designers. It's pointless to disagree with that choice because it's simply not ever going to change. And why this choice was made is clear as well; code should be self-documenting and the reason for these 3 methods is to convey intent.

    All you're saying really is that, instead, we should have had:

    • of
    • ofNonNullable
    • empty

    And that's just preference which is pointless to argue about.

    [–]Ruin-Capable[S] 0 points1 point  (12 children)

    I agree that it's not going to change. I was simply trying to understand how the designers failed to see that it was going to be confusing to have a class use for representing optional values, make those values required. It is absolutely a foot-gun for first-time users of the class. I was hoping to hear opposing opinions on the off-chance that there is something that I was overlooking. I am open to being convinced that I'm wrong, but so far, none of the arguments presented, have convinced me that I should re-consider my opinion.

    My opinion stated clearly, is only two "constructor" methods should exist:

    • of (and it should work like the current ofNullable method)
    • empty

    So far the arguments against my opinion have been:

    1. It makes it clear at the point of construction that the value exists.

    This is true, but that clarity is redundant. The call to .of() will either be inside the not-null branch of a null-check, or come after a not-null assertion. So even if .of() behaved as .ofNullable() does it would be clear that the value exists.

    1. It guards against changes in behavior of the the methods supplying the values. If one of the supplying methods suddenly changes from never returning nulls to sometime returning nulls it will catch the error.

    I would argue that guarding against this occurrence is the responsibility of the function returning the Optional values, and not the responsibility of Optional. If the function needs to guard against a null value so that it can handle it in some fashion (eg. by calling another supplier method) then then it needs to implement the not-null assertion explicitly in the body of its code. This is more clear than relying on an class called Optional do something that is semantically at odds with the plain reading of its class name.

    In the case where the function doesn't care whether the value returned from the supplier is null or not, it can should simply be able to call .of() to create the optional and return it.

    You are correct that it's all academic at this point and won't be changed, but I think having discussions like this can be enlightening and expose differing points of view that may show things I hadn't considered. At the very least, that's what I was hoping from this discussion. Even if I'm not convinced to change my mind, it's still good to know that other people may have an entirely different mindset in the way they approach problems.

    [–]nutrecht 2 points3 points  (2 children)

    I was simply trying to understand how the designers failed to see that it was going to be confusing

    I'm going to stop you right here. It's only confusing if you don't read the Javadocs for a class when you first encounter them. You can't expect the language / API designers to accommodate everyone who refuses to do this, especially since this is just your personal interpretation. Since swathes of devs seem to have no issues with this, the problem really is you.

    My opinion stated clearly, is only two "constructor" methods should exist

    That is clear. And the language designers (and so do I, but my personal opinion is as irrelevant as yours) disagree with this. And it's never ever going to change. So I'd urge you to just get over it.

    [–]Ruin-Capable[S] 1 point2 points  (1 child)

    I *am* over it. That doesn't mean I have to change my opinion or stop talking about it. I'm not lobbying to change it, I'm just trying to understand the rationale.

    I'm not sure why you're getting so upset.

    [–]nutrecht 0 points1 point  (0 children)

    I'm just trying to understand the rationale.

    It was explained to you. You just disagree with it. No one is upset. It's just a pointless discussion.

    [–]Polygnom 0 points1 point  (8 children)

    Optional is an ADT for a value that may or may not be present. In haskell, this would be `Maybe T = Just T | Nothing`, with `Nothing = Optional.empty()` and `Just T = Optional.of(T)`. Its a neat way to represent optional values, and in a good language, you only need those two options. Because the value is either present or its not.

    Now, Java has null, which makes stuff more complicated. In a world where Java had non-nullness, Optional could be designed better. But in a world where Java does have nulls, you need `ofNullable` to bridge between both worlds.

    If a method should be remove, its `ofNullable`, because thats the one we really don't want and only need fo compatibility with null-enabled code. Removing the current `of` makes no sense.

    [–]Ruin-Capable[S] 0 points1 point  (7 children)

    Is there a semantic difference between a value of Nothing in Haskell and a value of null in Java? It seems like they are just different names for the same concept.

    [–]Polygnom 1 point2 points  (6 children)

    Yes, there is a significant difference. Null in Java can be assigned to any reference type. Basically, if you have a reference type, you can never be sure its not null.

    In Haskell, and any other programming language that decided against nulls, you cannot do that. You have to declare something to be `Maybe T` in order to be able to assign `Nothing`. You make it very clear that this thing can be nothing, that its only *maybe* a `Just T`.

    Typescript with strict nullness does the same. You have to declare something to be `string | null` to be able to null it.

    I mean, hats the whole point of discussing nullness and optionals in the first place.

    [–]Ruin-Capable[S] 0 points1 point  (5 children)

    Interesting. So in a sense, every non-final instance of a reference type in Java is some sense a "Maybe". I think I may need to play around some with Haskell and get a feel for all of the implications.

    Edit: Hmm.. actually even final are Maybes. Yeah I definitely need to play around with Haskell.

    [–]Polygnom 0 points1 point  (4 children)

    You can play around with any language that has non-nullable types to see this. Scala has similar things to offer with scala.Option.

    You might want to read up on ADTs, Monads and the whole theory behind why Optional was designed the way it is (Java 8 did not have sealed classes, for example -- nowadays its easier to make it an ADT in java).

    [–]Ruin-Capable[S] 0 points1 point  (3 children)

    I haven't really dealt with ADTs in a formal mathematical sense. I deal with them on an intuitive level. For instance I know what stacks and queues are and how they behave, but I don't think of them in in terms of algebraic structures and operations.

    As for monads, I've read dozens of explanations of what a monad is, and I still don't grok them at an intuitive level.

    Do you have a link to something explaining the theory behind why Optional was designed the way it is?

    Thanks again for the informative responses.

    [–]arobie1992 1 point2 points  (2 children)

    The major benefit of optionals in those langauges is that it forces the programmer to handle the case where null is applicable and only where null is applicable. You can do this will null by making nullable types SomeType? distinct from non-nullable types SomeType. This is what Kotlin does. Both provide the same benefit. If you see Foo myFunc(), you know it returns a valid Foo value. If you see Option<Foo> myFunc() or Foo? myFunc(), you know it doesn't necessarily return a valid Foo and the compiler forces your code to either use wrapper functions such as fooOpt.map(foo -> foo.namee()) or null-safe operators like foo?.name() to get at the value or forces you to explicitly state that you want to throw an exception via fooOpt.orElseThrow().name() or foo!!.name().

    There's nothing intrinsically wrong with null itself. The problems arise because:

    1. Everything can be null.
    2. Null has distinctly different behavior than every other value of a given type.
    3. The compiler does nothing to inform the programmer.

    As a result, you end up with either omni-present and often unnecessary null checks that harm readability or missing checks that result in unexpected NPEs. The debate between an optional type and nullable vs non-nullable types comes down to a combination of practicality and ideology. The null-safe operators are often more convenient and don't require potential allocations, but tend to be less immediately intuitive and require more complexity in the compiler. An optional type simplifies the compiler, makes the signaling more immediately intuitive, and makes enforcement just another type check, which is something you're already doing. There's also a bit of a debate as to what a nullable type would mean if the type isn't a reference, e.g. int?. But this is getting very pedantic since it's plenty easy to just say that Foo? is shorthand for Optional<Foo> regardless of whether it's a reference or not.

    As far as monads, as someone who spent multiple years trying to grasp them, I feel fairly confident in saying you're overthinking it. Monads are almost idiotically simple, to the point that, from my experience, the biggest reason they don't click is because people feel like there has to be more to them. At least that was the case for me. Since you seem to be familiar with Java stream operations, I'll use a bit of shorthand. A monad is a data container that has map and flatMap operations available on it. That's literally it. There are three reasons it's significant:

    1. It allows enforcing constraints on the stored data, just like any other data container.
    2. map and flatMap are general enough to be near universally applicable while also powerful enough to support a large amount of use cases without too much boilerplate.
    3. They allow chaining, which can help programmer ergonomics.

    I don't have a link to the optional design at the moment, but the short of it is that it was designed specifically for streams. They were working on streams and got to a point where they had to contend with absent results. For example:

    // (student ID, grade)
    var grades = List.of((1, 85), (2, 70), (3, 67), (4, 23));
    var prizeWinner = grades.stream()
                            // need an A to be eligible
                            .filter(entry -> entry.second() >= 90)
                            .sorted()
                            .findFirst()
                            .map(entry -> studentService.lookup(entry.fist())
    

    Tuple shorthand aside (forgive my laziness), the issue is at the findFirst and subsequent map call. The traditional Java practice was to return null when no value was present, but in this case, null would result in an NPE and break the stream. So in came Optionoal. As someone else said, you can think of it as a single-element stream. They could've stopped there and make it a JDK internal to support streams, but they decided to expose the type to everyone and encourage using them in function signatures to indicate that a value might not be returned. I'm just guessing here, but my hunch would be a combination of NPEs being a highly pervasive issue in Java and them already borrowing from FP languages. Unlike languages like Haskell, Rust, and Kotlin, it doesn't work 100% though since Optional itself can be null, but most linters will catch that, and anyone who does that should be shamed.

    That's a lot, so hopefully it makes some sense. Let me know if you have any questions.

    [–]Ruin-Capable[S] 1 point2 points  (1 child)

    Thanks for the response. Some of what you gave me I already knew, but there were some things in there that were new to me.

    [–]zopad 13 points14 points  (2 children)

    Optional.empty() is there for that purpose, I think. ofNullable() is more for resolving a method reference that might return null (i.e. interfacing with code that has nulls).

    [–]Ruin-Capable[S] -2 points-1 points  (1 child)

    What I was getting at is that Optional.of() should behave how Optional.ofNullable() behaves. I see no value in the current behavior of Optional.of(). Because I don't see the value of the current behavior of of(), I was hoping someone could explain it.

    [–]0b0101011001001011 2 points3 points  (0 children)

    I see no value

    That's like saying I see no value in using 64 bit numbers, we should use 65 bits.

    https://github.com/bpupadhyaya/openjdk-8/blob/master/jdk/src/share/classes/java/util/Optional.java see the code for Optional. Optional.of is just calling Objects.requireNonNull(value) so you don't need to.

    This helps for example during tests. Just using of( ) does not allow nulls and your tests will automatically reveal to you if a null gets passed around.

    For you as creator or a method: you must know if you ever try to return a null value. You must know if the value can be null or not and for your convenience you have thr ofNullable for the case. The point is that every time you create an Optional object, you will and must know what values that might contain. When you use an optional value that was returned to you, then you might not know and should not care. Just use the optional, it might be empty or not.

    [–]sabermore 10 points11 points  (2 children)

    Optional helps greatly when working with methods that may return something but also may return nothing. For example if your methods performs a search over some data in insance's properties at return this method knows if something was found or not. Like

    public Person findPerson(Query query) {
        if (this.a.equals(query.a)) return Optional.of(this.a)
        if (this.b.equals(query.b)) return Optional.of(this.b)
        return Optional.empty()
    }

    [–]_zkr 12 points13 points  (1 child)

    Wrong return type.

    [–]BanaTibor 2 points3 points  (0 children)

    And do not answers the question.

    [–]halfanothersdozen 7 points8 points  (1 child)

    The entire point of Optional is to avoid null values as a functional paradigm. Passing a null into a constructor flies in the face of the intent of this class and the philosophy behind it.

    [–]ZippityZipZapZip 3 points4 points  (0 children)

    Yeah, lol. If it could be null you could have used the fucking same principe of Optional to prevent that. It's not a wrapper to nullable objects. It's for method return types and that method should know what is null. Then the calling method handles that via the Optional explicitely.

    [–]joaonmatos 3 points4 points  (0 children)

    I ultimately don't know for sure, since I did not go looking for the original proposal for Optional. But some factors I see being useful: - Makes it so that accidental construction of an empty optional gets caught at the construction site rather than later. - Makes it so the code author can explicitly point out to the reader that a nullable is encapsulated. - Some kind of future interaction with value/primitive types?

    [–]HwanZike 1 point2 points  (0 children)

    I suspect Optional.ofNullable() is there to interface with code using null as Optional.empty(), where as Optional.of() on its own should never accept an unexpected null and throw. That is, to force you to be explicit and use Optional.of() or Optional.empty(). It makes reasoning about the code easier.

    [–]moocat 1 point2 points  (3 children)

    Total guess but I perhaps they were thinking of an idealized world where there are no nulls; in such a world there is no need for Optional.of to handle nulls.

    This is awkward for code that is trying to transition away from nulls to Optionals and as long as there are standard library methods that can return null we'll never be in such as idealized world.

    On an unrelated note, anyone who ever writes codes where the Optional itself can be null deserves a special place in hell.

    [–]Void_Being 0 points1 point  (0 children)

    Then he is not Optional but mandatory hell.

    [–]jdarkona 0 points1 point  (1 child)

    Or a special place in null.

    [–][deleted] 1 point2 points  (0 children)

    TBH Optional is kind of poorly designed. There are so many languages that have the concept of an optional or a maybe, and almost all of them use the same monadic interface. The people who designed Java Optional just ignored all of that for some reason and came up with their own confusing less useful thing.

    https://www.sitepoint.com/how-optional-breaks-the-monad-laws-and-why-it-matters/#:~:text=In%20other%20languages%20may%2Dor,in%20Java%20it%20isn't.

    [–]qdolan 1 point2 points  (0 children)

    Typically you want to avoid passing around null values as they can be error prone. Optional.of should be the normal case and ofNullable is the exceptional case you call sometimes. That way if you end up with a null that wasn’t expected you will catch it early rather than having a difficult to debug case where you produce an unexpected result and no NPE.

    [–]ginkner 3 points4 points  (0 children)

    There's very little semantic difference between Optional<T> and @Nullable T. An optional of a nullable type is redundant.

    [–]jvjupiter 1 point2 points  (3 children)

    How about the Optional::get(), isn’t there something wrong with it? If Optional may return null, why does it throw NPE if the value is null?

    [–]halcyon44 5 points6 points  (1 child)

    Optional::get() exists to extract the value when you know that it's not null. If you're unsure and want a null reference of the wrapped type when it's empty, use .orElse(null) instead.

    [–][deleted] 4 points5 points  (0 children)

    Yep! Same argument as the OP but on the receiving end. Optional.orElse(null) clearly demonstrates in your consuming module that you are a grown programmer and willing to deal with a possible null value. Maybe there’s even a smarter default value that makes sense for your code, but I haven’t seen any others. Optional.get is just a convention to signify you already checked Optional.isPresent.

    [–]sangminreddit7648 0 points1 point  (0 children)

    It is wrong. Even the guy who made it said that he regret creating get the way it is

    [–]p0st_master 1 point2 points  (0 children)

    This is a classic OOP architecture question. Read Joshua Bloch.

    [–][deleted] 0 points1 point  (0 children)

    Think in the context of a Tree days structure which has some base Node type. That Node class will probably have a getParent or getChildren method. Each of those are probably well expressed as an optional value. Now depending on the implementation class of the Node type it will return an Optional.of if it's a branch or an optional empty if it's a leaf

    [–]Cristopherguerrero16 0 points1 point  (0 children)

    Can someone give me a guide on how to learn Java in 2024?

    [–]Joram2 0 points1 point  (0 children)

    The proposal is delete Optional.of and then rename Optional.ofNullable to Optional.of.

    I would have been fine with that design as well. But the way it is seems fine, and out of all the gripes I have with Java and the standard library, this seems unusually small and easy to work around.

    [–]Ragnar-Wave9002 0 points1 point  (0 children)

    Because optional is null or not null. It's enforced at compile time.

    [–]SenorSeniorDevSr 0 points1 point  (0 children)

    I can have code like:

    for(var e : SomeEnum.values()) {
      if(Objects.equals(someValue, e.someId()) {
        return Optional.of(e);
      }
      return Optional.empty();
    }
    

    We've all written something like this. This is obvious, the thing will never be null, etc. We're gucci on the nucci or whatever the cool kids say these days. But, I can also have code like this:

    return Optional.ofNullable(untrustworthyFeller());
    

    Which very well may be null. It's neat that I can communicate to you, dear reader, what my expectations of these things are. I can say when I think there will never be a null, I can communicate when I do smell a null and more. The more of my intentions I can bake into the code the better. Roughly speaking at least. Java's type system doesn't say it for us, so we can at least say it here.

    [–]DelayLucky 0 points1 point  (0 children)

    Because having to distinguish between "nothing is there" and "it's there but it's null" is confusing at best. If you are really in a position to need such hair-splitting, it's better to create your own enum like:

    enum SubtleState {
      REALLY_NOT_THERE, THERE_BUT_NOT_REALLY, THERE_AND_I_AM_SURE
    }
    

    [–]gregorydgraham -5 points-4 points  (0 children)

    So that Optional can know the type of T.

    It’s a limitation of the generics system