Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shortcut for Guava's Optional use with exceptions?

Tags:

java

guava

I keep writing specific exception throwers in the case the Optional is absent.

For instance:

Optional<?> optional = ...;
if (!optional.isPresent()) {
  throw new MyException();
}
Object result = optional.get();

I find this code not very fluent, especially the use of the bang (!). I'd rather like writing something like:

Optional<?> optional = ...;
Object result = optional.orThrow(MyException.class);

Is there such a shortcut in Guava that I haven't found yet?

like image 619
Olivier Grégoire Avatar asked Dec 16 '11 12:12

Olivier Grégoire


People also ask

What does Optional absent return?

Returns the value of each present instance from the supplied optionals , in order, skipping over occurrences of absent() . Returns a string representation for this instance. If the instance is present, it is transformed with the given Function ; otherwise, absent() is returned.

Is optional absent null?

Introduction : Optional is an immutable object that may contain a non-null reference to another object. Each instance of this type either contains a non-null reference, or contains nothing, in which case we say that the reference is absent. It is never said to contain null.


3 Answers

Speaking as a Guava developer, let me try to unpack the logic here. Responding both to the original question, and the comment thread directly on the question:

It is absolutely the case that we try to force Guava users to respect our standards of good programming habits. (Our standards are strongly influenced by e.g. Effective Java.)

That said, I agree that there are perfectly good use cases for the behavior you're referring to in this particular question: "if absent, throw an exception." Perhaps you're implementing a class that can be accessed both ways -- one method with an Optional return value, and one method that assumes that the value will always be present, throwing an exception otherwise. The Deque interface, for instance, provides special-valued and exception-throwing versions of peek, poll, and offer.

All that said, to the best of my understanding, the True Guava Way to do this is...

if (value.isPresent()) {
  return value.get();
} else {
  throw new MyException();
}

The "orThrow" method you propose requires reflection (!!), doesn't let you customize the exception with a useful message, etc. The "normal way" is perfectly readable and more efficient.

Sometimes Guava doesn't provide explicit support for things because for those use cases, we think it's best done just the "normal way." I think this is the case here.

like image 113
Louis Wasserman Avatar answered Nov 15 '22 20:11

Louis Wasserman


It is worth nothing that Java 8's Optional has an orElseThrow(Supplier) method that allows the requested behavior.

It is used like this:

Optional<Object> reference = Optional.empty()
reference.orElseThrow(MyOwnException::new); // Throws a new MyOwnException

Furthermore, a method in Java 10 was added, orElseThrow(), which throws a NoSuchElementException if no value is present.

Optional<Object> reference = Optional.empty();
reference.orElseThrow(); // Throws a new NoSuchElementException
like image 35
Olivier Grégoire Avatar answered Nov 15 '22 19:11

Olivier Grégoire


Here's another way to do it without additions to Guava:

Object result = optional.or(new Supplier() {
    public Object get() {
        throw new MyException();
    }
});

MyException has to be unchecked, but this does allow you to pass arguments to its constructor. And of course if you're doing it a lot you can store the Supplier somewhere and use it each place you need it.

Object result = optional.or(SomethingIsMissing.INSTANCE);
like image 26
TimK Avatar answered Nov 15 '22 20:11

TimK