Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What to return when generic methods returns 'nothing' but null can't be returned?

Suppose I have a library method like this (very abbreviated):

public static <V> Optional<V> doSomethingWith(Callable<V> callable) {
    try {
        return Optional.of(callable.call());
    } catch (Exception ex) {
        // Do something with ex
        return Optional.empty();
    }
}

And I want to something that doesn't return a value, like:

    Library.</*What1*/>doSomethingWith(() -> {
        foo();
        return /*what2*/;
    });

My first instinct for a generic method that doesn't return a value is making the type Void and returning null, however because the result gets wrapped in an Optional this would throw an exception.

What are reasonable placeholders for /*What1*/ and /*what2*/ that don't look totally random like Integer and 0?

[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.

like image 869
Mark Jeronimus Avatar asked Dec 28 '16 10:12

Mark Jeronimus


2 Answers

If you need a type hint for a generic parameter that will never be used you can use Void, the JDK does this too in some cases, e.g. when converting Runnable into CompletableFuture<T> it uses Void for T.

If you use Optional.ofNullable then you can just return null for what2, which is the only valid value for Void.

[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.

Then you're using the wrong tool for the job. CompletionStage or CompletableFuture has the right semantics.

like image 200
the8472 Avatar answered Sep 23 '22 09:09

the8472


I usually use Boolean.TRUE to mark success, but you could return Void.class as well. Both are cheap in the sense that not every return creates a new object to be discarded. Though Class<Void> is not just Void it may serve the purpose of labelling something as void just as well.

As already mentioned you could also create your own Result-class/-enum.

Or you could of course return Optional.<Void>nothing(), too. This would result in some Optional<Optional<Void>>, but also do the trick.

If you think all of the above is ugly, I fear that the API probably isn't to well tailored to your needs. Raise an issue/pull request or look for something else.

like image 28
TheConstructor Avatar answered Sep 22 '22 09:09

TheConstructor