Uses For Optional

Uses for Optional

The main design goal of Optional is to provide a means for a function returning a value to indicate the absence of a return value. See this discussion. This allows the caller to continue a chain of fluent method calls.

This most closely matches use case #1 in the OP's question. Although, absence of a value is a more precise formulation than null since something like IntStream.findFirst could never return null.


For use case #2, passing an optional argument to a method, this could be made to work, but it's rather clumsy. Suppose you have a method that takes a string followed by an optional second string. Accepting an Optional as the second arg would result in code like this:

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

Even accepting null is nicer:

foo("bar", "baz");
foo("bar", null);

Probably the best is to have an overloaded method that accepts a single string argument and provides a default for the second:

foo("bar", "baz");
foo("bar");

This does have limitations, but it's much nicer than either of the above.

Use cases #3 and #4, having an Optional in a class field or in a data structure, is considered a misuse of the API. First, it goes against the main design goal of Optional as stated at the top. Second, it doesn't add any value.

There are three ways to deal with the absence of a value in an Optional: to provide a substitute value, to call a function to provide a substitute value, or to throw an exception. If you're storing into a field, you'd do this at initialization or assignment time. If you're adding values into a list, as the OP mentioned, you have the additional choice of simply not adding the value, thereby "flattening" out absent values.

I'm sure somebody could come up with some contrived cases where they really want to store an Optional in a field or a collection, but in general, it is best to avoid doing this.

Java 8 Optional. Why of and ofNullable?

The javadoc of Optional.of reads that explicitly :

@throws NullPointerException if value is null

and that is where the requirement of handling the cases as expected by you comes into picture with the use of Optional.ofNullable which is a small block of code as :

public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value); // 'Optional.of'
}

That said, the decision of choosing one over the other would still reside with the application design as if your value could possibly be null or not.


On your expectation part, that was not what the Optional was actually intended for. The API note clarifies this further (formatting mine):

Optional is primarily intended for use as a method return type where
there is a clear need to represent "no result," and where using
null is likely to cause error. A variable whose type is Optional should never itself be null; it should always point to an Optional instance.


purpose of Optional is to tackle NullPointerException exception.

Aside: Just to call it out clearly, that the choice would of course implicitly let you define if an NPE should be thrown at runtime or not. It's not determined at the compile time though.

Optional vs. null. What is the purpose of Optional in Java 8?

In practice, why is this useful?

For example let's say you have this stream of integers and you're doing a filtering:

int x = IntStream.of(1, -3, 5)
.filter(x -> x % 2 == 0)
.findFirst(); //hypothetical assuming that there's no Optional in the API

You don't know in advance that the filter operation will remove all the values in the Stream.

Assume that there would be no Optional in the API. In this case, what should findFirst return?

The only possible way would be to throw an exception such as NoSuchElementException, which is IMO rather annoying, as I don't think it should stop the execution of your program (or you'd have to catch the exception, not very convenient either) and the filtering criteria could be more complex than that.

With the use of Optional, it's up to the caller to check whether the Optional is empty or not (i.e if your computation resulted in a value or not).

With reference type, you could also return null (but null could be a possible value in the case you filter only null values; so we're back to the exception case).

Concerning non-stream usages, in addition to prevent NPE, I think it also helps to design a more explicit API saying that the value may be present or not. For example consider this class:

class Car {
RadioCar radioCar; //may be null or not
public Optional<RadioCar> getRadioCar() {
return Optional.ofNullable(radioCar);
}
}

Here you are clearly saying to the caller that the radio in the car is optional, it might be or not there.

What is the difference between Optional.ofNullable() and `Optional.of()

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.

I would like to know about the meaningful usage of Optional orElseGet

You don't exactly give enough context to give a meaningful specific answer.

For users, a sensible usage could be

UserEntity user = userRepo.getUser(userId).orElseGet(() -> userRepo.getGuestUser());

It really depends on the use case.

Proper usage of Optional.ifPresent()

Optional<User>.ifPresent() takes a Consumer<? super User> as argument. You're passing it an expression whose type is void. So that doesn't compile.

A Consumer is intended to be implemented as a lambda expression:

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

Or even simpler, using a method reference:

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

This is basically the same thing as

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
@Override
public void accept(User theUser) {
doSomethingWithUser(theUser);
}
});

The idea is that the doSomethingWithUser() method call will only be executed if the user is present. Your code executes the method call directly, and tries to pass its void result to ifPresent().



Related Topics



Leave a reply



Submit