Daniel Rikowski
Daniel Rikowski

Reputation: 72514

What do I return if the return type of a method is Void? (Not void!)

Due to the use of Generics in Java I ended up in having to implement a function having Void as return type:

public Void doSomething() {
    //...
}

and the compiler demands that I return something. For now I'm just returning null, but I'm wondering if that is good coding practice...

I'm asking about V‌oid, not v‌oid. The class Void, not the reserved keyword void.

I've also tried Void.class, void, Void.TYPE, new Void(), no return at all, but all that doesn't work at all. (For more or less obvious reasons) (See this answer for details)

Upvotes: 122

Views: 74061

Answers (7)

Basil Bourque
Basil Bourque

Reputation: 338730

Example use case: Callable tasks with ExecutorService

What's the general use of the Void class?

One use is to make clear that you have no intention of returning a value in a situation where a return value is demanded.

In what case could that happen? One realistic scenario is where you are using a ExecutorService to run tasks on other thread(s).

Example task:

class Bogus implements Runnable
{
    @Override
    public void run ( )
    {
        System.out.println ( "INFO - Performing our task." );
    }
}

Suppose we want to submit a bunch of those Runnable task instances. We would call invokeAll. But that method takes only a collection of Callable objects, not Runnable objects. The difference here is that Callable represents a task that returns a result object, while Runnable represents a task that returns nothing.

To be able to call invokeAll, we must convert our Runnable objects to be Callable. But we have no result to return. The type of that result will be the parameterized type of our Callable. With nothing to return, what should be the parameterized type for our particular Callable implementation?

Well, we could use Object.

class Bogus implements Callable < Object >
{
    @Override
    public Void call ( ) throws Exception
    {
        System.out.println ("INFO - Performing our task." );
        return null;
    }
}

But using Object there is weird. The programmer reading this code will be surprised to see Object appear at all. And then upon further reading, the programmer reading this code will realize that actually nothing is ever returned. That makes for puzzling reading.

So if not Object, what then? Well first thought is void, but that does not work syntactically. The solution: Void class. The use of this class shouts out loud to the reader that we have no intention of returning anything. And the use of Void class satisfies the compiler.

class Bogus implements Callable < Void >
{
    @Override
    public Void call ( ) throws Exception
    {
        System.out.println ("INFO - Performing our task." );
        return null;
    }
}

Note that we are not actually returning an object of type Void. We return a null, nothing at all. We are simply using that class name as the declared parameterized type to make more clear our intention in a less-than-optimal situation. (Optimal would be invokeAll accepting a collection of Runnable objects. I’ve no idea why it does not.)

Similar to the code above, this class Void will be the parameterized type of our List of Future objects returned by ExecutorService#invokeAll. In the following code, notice List < Future < Void > > futures.

Collection < Bogus > tasks =
        List.of (
                new Bogus ( ) ,
                new Bogus ( ) ,
                new Bogus ( )
        );
try
        (
                ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor ( ) ;
        )
{
    List < Future < Void > > futures = executorService.invokeAll ( tasks );
}
catch ( InterruptedException e )
{
    throw new RuntimeException ( e );
}

Upvotes: 0

Jang-Ho Bae
Jang-Ho Bae

Reputation: 516

just like this.

public Class TestClass {
    public void testMethod () {
        return;
    }
}

Upvotes: -5

John Feminella
John Feminella

Reputation: 311536

So what am I supposed to return if the return type of a function has to be Void?

Use return null. Void can't be instantiated and is merely a placeholder for the Class<T> type of void.

What's the point of Void?

As noted above, it's a placeholder. Void is what you'll get back if you, for example, use reflection to look at a method with a return type of void. (Technically, you'll get back Class<Void>.) It has other assorted uses along these lines, like if you want to parameterize a Callable<T>.

Due to the use of generics in Java I ended up in having to implement this function

I'd say that something may be funky with your API if you needed to implement a method with this signature. Consider carefully whether there's a better way to do what you want (perhaps you can provide more details in a different, follow-up question?). I'm a little suspicious, since this only came up "due to the use of generics".

Upvotes: 109

Martijn
Martijn

Reputation: 6763

To make clear why the other suggestions you gave don't work:

Void.class and Void.TYPE point to the same object and are of type Class<Void>, not of Void.

That is why you can't return those values. new Void() would be of type Void but that constructor doesn't exist. In fact, Void has no public constructors and so cannot be instantiated: You can never have any object of type Void except for the polymorphic null.

Hope this helps! :-)

Upvotes: 21

Jon Bright
Jon Bright

Reputation: 13738

There's no way to instantiate a Void, so the only thing you can return is null.

Upvotes: 28

PhiLho
PhiLho

Reputation: 41142

If, for obscure reasons, you MUST use this type, then indeed returning null seems to be a sensible option, since I suppose return value will not be used anyway.
The compiler will force you to return something anyway.
And this class doesn't seem to have a public constructor so new Void() is not possible.

Upvotes: 1

Bombe
Bombe

Reputation: 83850

return null is the way to go.

Upvotes: 21

Related Questions