Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why optionalLong/Double and orElseThrow?

Tags:

java

java-10

With release of Java-11, Why do we have orElseThrow with optionalLong / OptionalDouble and other Optional Types when we can directly check if a number is not null or not equals to a specific number.

Also, we were doing null checks which were better than throwing an Exception?

May be not able to visualize the real use of optionalTypes and orElseThrow.

Javadoc for orElseThrow.

like image 433
Chetna rustagi Avatar asked Jul 31 '19 10:07

Chetna rustagi


People also ask

Why is null better than optional?

In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.

What is OptionalLong?

public final class OptionalLong extends Object. A container object which may or may not contain a long value. If a value is present, isPresent() returns true . If no value is present, the object is considered empty and isPresent() returns false .

Why is optional required?

Optional is intended to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.

Why we should use optional in Java?

Core Java bootcamp program with Hands on practice Optional is a container object used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values.


2 Answers

I randomly chose a method from com.google.common.io API which demonstrates the use of Optional<Long>. They use own Optional type, but the concept is identical.

@Override
public Optional<Long> sizeIfKnown() {
  if (file.isFile()) {
    return Optional.of(file.length());
  } else {
    return Optional.absent();
  }
}

Due to the absence of OptionalLong, they are auto-wrapping file.length(), which returns a long, into an Optional<Long>. They don't want sizeIfKnown to throw an exception. They don't want sizeIfKnown to introduce a magical return value which would indicate the absence of a value.

Instead, they want to say "we return a long, or nothing".

With Java 11, it would look a bit cleaner, and a bit simpler

@Override
public OptionalLong sizeIfKnown() {
  if (file.isFile()) {
    return OptionalLong.of(file.length());
  } else {
    return OptionalLong.empty();
  }
}

Regarding orElseThrow, it's relatively old feature introduced in Java 8 to control execution flow in a functional manner. It does exactly what you described: a null check and a throw statement.

if (value != null) {
    return value;
} else {
    throw exceptionSupplier.get();
}
like image 160
Andrew Tobilko Avatar answered Nov 14 '22 23:11

Andrew Tobilko


Why do we have orElseThrow with optionalLong / OptionalDouble when we can directly check if a number is not null or not equals to a specific number.

Not really, Optionals are designed for return types, not for checking input parameters. In the later cases, checking not null or range validity (for primitives) makes more sense.
Besides, these features are not new. Java 8 already introduced these functions.


To illustrate the interest of OptionalLong.orElseThrow(), suppose a case where you search a long id from a method but that id may not be found.
Here is a code that handles the not found value case.

Without OptionalLong, you should choose an arbitrary long value to convey the not found result :

long id = compute();  // returns -1. By hopping that it not a valid id...

Then, from the client side, you have to dig into the implementation of compute() to know if the id value can be empty and whether is the case, which value represents the emptiness.
And at last you could write that :

if (id == -1){
   throw  new IllegalArgumentException("the id is mandatory");
}

Suppose that tomorrow -1 be a valid id, so you should change both the implementation and the client code to be aware of it : not maintainable at all and very error prone.

With OptionalLong the approach is much more robust :

OptionalLong optId = compute(); // returns OptionalLong.empty();

As a client of compute() you know that the id may be empty (Optional semantic) and you know also how to handle it in a standard way: the Optional` unwrapping functions.

long mandatoryId = optId.orElseThrow( ()-> new IllegalArgumentException("the id is mandatory");  

Here OptionalLong or even Optional<Long> provides a triple advantage (about the difference between them I advise the excellent answer of Nishant) :

  • living documentation of the emptiness case return
  • robustness way for clients to convey the emptiness value (versus the -1 approach).
  • standard way to convey and handle the emptiness return (Optional and its functions)

But in a general way, Optionals with Objects contained in provides "only" these two advantages :

  • living documentation of the emptiness case return
  • standard way to convey and handle the emptiness return (Optional and its functions)
like image 44
davidxxx Avatar answered Nov 14 '22 22:11

davidxxx