3

First of all, I know the difference between the two methods.

  • Optional.of : Used to ensure that there is no null, if null is entered, nullPointExcepction

  • Optional.ofNullable : may or may not be null. Used to respond flexibly.

So, if I add orElseThrow(() -> new NullPointerException("null data")) to this, will it end up being the same?

I want to throw an error with explicit content.

So I get Optional.ofNullable(data).orElseThrow(() -> new NullPointerException("null data")))

use it as Is this pointless behaviour?

Optional.of(data).orElseThrow(() -> new NullPointerException("null data")))

I think this is also possible, but I'm just using ofNullable() to make the code look consistent.

to sum it up, In the end, if you add orElseThrow(nullPoint) Are of or ofNullable the same result?

then rather Is of.orElseThrow better?

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
바보린
  • 159
  • 1
  • 13
  • There's a third way to get an NPE: `orElseThrow(null)` – shmosel Apr 12 '22 at 01:31
  • Beyond simply getting the npe, I want to send a message to the npe. (The process of printing this is prepared.) In the end I have no choice but to use orElseThrow(() -> new NullPointerException("message")) to achieve what I want? – 바보린 Apr 12 '22 at 01:36
  • Yes, if you want to customize the exception, you should use `orElseThrow`. – shmosel Apr 12 '22 at 01:45
  • 1
    That is if you're doing something else in the Optional chain. Calling it immediately after initializing the Optional would be weird. – shmosel Apr 12 '22 at 01:51

2 Answers2

9

to sum it up, In the end, if you add orElseThrow(nullPoint) Are of or ofNullable the same result?

No. To see this, simply look at the types.

public static <T> Optional<T> of(T value);

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
                               throws X extends Throwable;

Optional.of returns an Optional<T>, where orElseThrow is going to leave you with a T. So Optional.ofNullable(x).orElseThrow(...) is really just a very roundabout

if (x == null) {
  throw new NullPointerException(...);
}

You're not actually doing anything with the Optional, just making one and discarding it in a really verbose way. So if that's your intent, just do an explicit null check; there's no need at all for Optional.

Which raises the question of why we would use of or ofNullable. With the introduction of Optional, there are now two ways to represent the concept of "this value might not exist" in Java: null and Optional.empty(). People on the Internet will argue till the end of time about which is better and when you should use which one (I have strong opinions on this which I'll refrain from sharing here, since it's not what you asked), but the point is that there are two different ways to do it.

For the rest of this post, I'll borrow a bit of notation from Kotlin and write T? to mean "a T value which might be null". It's not valid Java notation, but it gets the point across. So if we want to represent "A T which may or may not exist" in Java, we can use either Optional<T> or T?.

If we want to go from T? to Optional<T>, that's what Optional.ofNullable is for. It says "If the thing is null, give me Optional.empty(); otherwise give me the thing in an Optional". To go the other way, we can use Optional.orElse(null), which says "If I have a T, give it to me, otherwise show me null". So now we have a way to convert between the two approaches. So what's Optional.of for?

You should view Optional.of as an assertion of sorts. If Java had nullable types like Kotlin, then the difference would be something like

public static <T> Optional<T> of(T value);
public static <T> Optional<T> ofNullable(T? value);

That is, ofNullable expects that its value might be null. of is already assuming that it's not. Optional.of should be thought of an assertion that the value you're giving it is not null. If that assertion fails, we throw NullPointerException immediately rather than letting errors propagate to other parts of the program. If you're calling Optional.of and recovering from the NullPointerException it throws[1], then you are doing something very wrong. That function is an assertion we were dealing with non-null data to begin with, and if that assertion fails then your program should fail immediately with a good stack trace.

It sounds like, based on your use case, you have a value that might be null. In that case, Optional.ofNullable makes sense; it's prepared to handle the use case. If you want to throw a custom exception, you should do a null check beforehand (since you're the one handling the null, not Optional) and then call Optional.of. Or, of course, you can just do an old-fashioned null check and not use Optional at all, if you're planning to extract it anyway with orElseThrow. Certainly, the pipeline Optional.ofNullable(value).orElseThrow(...) in one line would be a code smell.


[1] Note that I say "recovering from", not "catching". A nice top-level catch (Exception exc) which logs all errors is perfectly acceptable and generally a good idea in larger applications. But if you're doing catch (NullPointerException exc) { return 0; } or something like that then you need to reconsider which Optional method you should be using.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116
  • Thank you very much for your valuable reply. After learning Optional, I mainly used it for validation. There must be a value, but in case it doesn't exist for some reason (malicious attack). Thanks to your answer, I thought my code was bad code. Is your intention correct? – 바보린 Apr 12 '22 at 02:32
  • A little more about my situation, There are values ​​a, b, and c, a and b must have a value, and c doesn't matter. At this time, I Optional.ofNullable (a).orElseThrow(() -> new NullPointerException(" a = null data"))) Optional.ofNullable (b).orElseThrow(() -> new NullPointerException("b = null data"))) I use it like this: Is it very wrong? – 바보린 Apr 12 '22 at 02:33
  • It sounds like you don't really need `Optional` at all. I would go with old-fashioned `if (a == null)` checks and throw exceptions explicitly. You're getting none of the benefits of `Optional` the way you're doing it and you're really just obfuscating the core point of the code, which is validation and a custom error. – Silvio Mayolo Apr 12 '22 at 02:42
  • After listening to you and checking again, I realized what mistake I had made. Thank you. I'm sorry to bother you with the continued question, but maybe Optional.of / Optional.ofNullable Can you point me to a situation or example of this meaningful use? – 바보린 Apr 12 '22 at 02:47
  • `Optional.of` is basically the constructor for `Optional`, so you use that when you want to *construct* an `Optional` out a value you already trust to be non-`null`. `Optional.ofNullable` is for converting potentially null values to `Optional` ones, for instance if you're coming from a library that uses `null` and you'd prefer to use `Optional` or vice versa. – Silvio Mayolo Apr 12 '22 at 02:50
  • I also think the if(a==null) method you mentioned is valid. However, I learned that the purpose of Optional is mostly to check for null. However, when used, it can actually reduce readability. I don't know how to use it correctly... – 바보린 Apr 12 '22 at 02:56
  • 2
    “If Java had nullable types” we would probably not need `Optional` at all. By the way, the idiomatic alternative to `if (x == null) { throw new NullPointerException(message); }` is [`Objects.requireNonNull(x, message);`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Objects.html#requireNonNull(T,java.lang.String)) – Holger Apr 12 '22 at 10:45
1

First of all, I know the difference between the two methods.

Optional.of : Used to ensure that there is no null, if null is entered, nullPointExcepction

Optional.ofNullable : may or may not be null. Used to respond flexibly.

There's a clear point of misunderstanding.

The purpose of Optional.of() is not "to ensure that there is no null". It is not meant to be used as an assertion that a value that was passed into it is non-null. For such a validation you can use Objects.requireNonNull(), it'll either throw an NPE, or will return you a non-null value.

In order to be on the same page, the first important thing you have to keep in mind is that optionals were introduced in the JDK for only one particular purpose - to serve as a return type. Any other cases when optional is utilized as a parameter-type, or a field-type, or when optional objects are being stored in a collection isn't considered to be a good practice. As well, as creating an optional just in order to chain methods on it or to hide a null-check is considered to be an antipattern.

Here is a couple of quotes from the answer by @StuartMarks, developer of the JDK:

The primary use of Optional is as follows:

Optional is intended to provide a limited mechanism for library method return types where there is a clear need to represent "no result," and where using null for that is overwhelmingly likely to cause errors.

A typical code smell is, instead of the code using method chaining to handle an Optional returned from some method, it creates an Optional from something that's nullable, in order to chain methods and avoid conditionals.

I also suggest you to have a look at this answer to the question "Should Optional.ofNullable() be used for null check?", also by Stuart Marks.

With all that being said, combination Optional.of().orElseThrow() is both wrong and pointless:

  • If provided data is null method of() will raise an NPE and orElseThrow() will not be executed (i.e. its exception will get never be fired).
  • You're abusing the optional by creating an optional object not in order to return a nullable variable wrapped by it, but to hide the null-check (take a look at the quote above). That obscures the purpose of your code. You can use Objects.requireNonNull() instead to throw an exception if the given value must not be null or requireNonNullElse() to provide a default value.

For the same reason, you shouldn't use Optional.ofNullable().orElseThrow() at the first place.

Optional is like a Box

You might think of optional is if it is a parcel. When you need to send something, you go to the post office (i.e. returning from the method), where the thing that has to be sent is being placed into a box. When somebody (i.e. the caller) receives the parcel, it is being immediately unpacked. That is the whole lifecycle of the box called Optional.

When, according to the logic of your application, an object required to be returned from the method should not be null - use Optional.of(). It'll either send a parcel successfully or will emphasize that there's a problem by raising a NullPointerException.

If the given object is nullable by its nature, i.e. null isn't an abnormal case, then use Optional.ofNullable(), it'll fire either a box containing the object or an empty box.

And the caller (i.e. method that invokes the method returning an optional) is the one who has to unpack the box using a variety of tools that optional provides like orElseThrow(), orElseGet(), ifPresent(), etc.

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • Thanks to you, I know how to use it correctly. Thank you. However, it was a bit difficult, so I didn't fully understand it. I know when not to use it, but I don't know when it's good to use it. If you don't mind, can you give me a simple example? – 바보린 Apr 12 '22 at 15:55
  • 1
    @바보린 Ok. Firstly, as a rule of thumb, don't stick the `Optional` in the middle of your methods. Let's assume have a method that processes the input somehow and using the resulting data it makes a call (to a library, to a legacy part of your system, a database query, important thing is that the value returned by that call can be `null`). And you must return that value at all cost, i.e. even if it is `null` (an indicator that request failed). So instead of returning `null` you can wrap it with an optional object by making of `Optional.ofNullable()`. – Alexander Ivanchenko Apr 12 '22 at 17:00
  • 1
    And when you have a method that returns `Optional` with several conditional statements, and there's a case when you are *certain* that the produced value is *non-null*, then you should use `Optional.of()`. Because it'll will be obvious to the reader of your code that this value isn't expected to be `null`, if you would utilize `ofNullable()` instead it might create confusion. That's how you can distinguish between them. – Alexander Ivanchenko Apr 12 '22 at 17:12
  • 1
    Also, remember a *simple rule*: every time you're returning `null`, stop and try to think of other option. Which are to use an `Optional`, to throw an exception right on the spot, or implement the *null-object pattern* (depending on your needs). – Alexander Ivanchenko Apr 12 '22 at 17:20
  • 1
    You've been very helpful, but I'm late to thank you. Thanks to your additional explanation, I just opened my eyes! – 바보린 Apr 14 '22 at 08:52