Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shorthand for "If/Throw, Else/Return" logic in Java 8?

Tags:

java

java-8

Is there a shorter syntax to if/throw else/return in Java 8? java.util.Optional provides a means to accomplish this in one statement, but it requires creating an Optional instance with every call that has a non-null reference.

Can this be accomplished in a single statement?

public static MyEnum fromString(String value) {
    MyEnum result = enumMap.get(value);
    if (result == null)
        throw new IllegalArgumentException("Unsupported value: " + value);
    return result;
}

Optional Example (bad, requires Optional instance every time)

public static MyEnum fromString(String value) {
    return Optional.ofNullable(enumMap.get(value)).orElseThrow(
        () -> new IllegalArgumentException("Unsupported value: " + value));
}
like image 924
Sam Berry Avatar asked Oct 22 '14 03:10

Sam Berry


2 Answers

The impact of a temporary Optional instance is negligible. Usually the JVM will detect its temporary nature and optimize away the instance. Even if the temporary instance creation is not optimized away, the impact of one single temporary object on the memory management is ridiculously low. See also GC overhead of Optional<T> in Java.

However, if the map is mutable, you can use the following trick:

public static MyEnum fromString(String value) {
    return enumMap.computeIfAbsent(value, v -> {
        throw new IllegalArgumentException("Unsupported value: " + v); });
}

Note that the Map is not modified by this code but still must be mutable as an immutable map might throw an UnsupportedOperation exception for the attempt to use computeIfAbsent without ever checking whether the operation would really modify the map.


But in the end, there is nothing wrong with Optional. But note that the code in your question is wrong. The lambda expression you pass to the method Optional.orElseThrow is meant to supply the desired exception, not to throw it:

public static MyEnum fromString(String value) {
    return Optional.ofNullable(enumMap.get(value)).orElseThrow(() ->
        new IllegalArgumentException("Unsupported value: " + value) // just return it
    );
}
like image 124
Holger Avatar answered Oct 22 '22 12:10

Holger


If you are willing to live with NullPointerException, you can do:

public static MyEnum fromString(String value) {
    return requireNonNull(enumMap.get(value), () -> "Unsupported: " + value);
}

This assumes import static java.util.Objects.requireNonNull

Edit:

If you are really particular about what type of exception you throw, just implement your own static utility method:

static<T, X extends Throwable> T nonNullOrThrow(T val, Supplier<? extends X> exSupplier) throws X {
    if (val != null) return val;
    else throw exSupplier.get();
}

Then you'll be able to do

return nonNullOrThrow(enumMap.get(value), () -> new IllegalArgumentException("unsupported: " + k));
like image 3
Misha Avatar answered Oct 22 '22 14:10

Misha