Reputation: 72514
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 Void, not void. 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)
Void
? Void
class?Upvotes: 122
Views: 74061
Reputation: 338730
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
Reputation: 516
just like this.
public Class TestClass {
public void testMethod () {
return;
}
}
Upvotes: -5
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
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
Reputation: 13738
There's no way to instantiate a Void, so the only thing you can return is null.
Upvotes: 28
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