I have a class which defines two overloaded methods
public void handle(Void e)
protected void handle()
Obviously they are different, esp
Consider the API to AsyncTask<T1, T2, T3>
from the Android system, which provides three hooks:
class AsyncTask<S, T, V> {
void doInBackground(S...);
void onProgressUpdate(T...);
void onPostExecute(V);
}
When you extend the generic type AsyncTask<T1, T2, T3>
you may not be interested in using parameters for the progress and result hooks, so your implementation will look like:
class HTTPDownloader extends AsyncTask<URL, Void, Void> {
void doInBackground(URL... urls) {}
void onProgressUpdate(Void... unused) {}
void onPostExecute(Void unused) {}
}
and you can invoke these methods with a null
parameter, since Void
can't be instantiated.
Void
is a special class usually used only for reflection - its primary use is to represent the return type of a void method. From the javadoc for Void:
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
Because the Void
class can not be instantiated, the only value you can pass to a method with a Void
type parameter, such as handle(Void e)
, is null
.
That's the official version of events, but for those who are interested, despite claims to the contrary in the javadoc of Void
, you can actually instantiate an instance of Void
:
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor!
That said, I have seen Void
"usefully" used as a generic parameter type when you want to indicate that the type is being "ignored", for example:
Callable<Void> ignoreResult = new Callable<Void> () {
public Void call() throws Exception {
// do something
return null; // only possible value for a Void type
}
}
Callable
's generic parameter is the return type, so when Void
is used like this, it's a clear signal to readers of the code that the returned value is not important, even though the use of the Callable
interface is required, for example if using the Executor
framework.
If Void
isn't actually an instantiation of a type parameter (where it obviously makes sense), there is also sense in declaring a handle(Void)
if your handle
method is subject to an extralinguistic contract that says that the object that wants to participate in a certain protocol must implement a one-argument handle method, regardless of the actual argument type. Now, there may be a special-case implementation that can't handle anything but null
so it makes sense to declare handle(Void)
for such an implementation.
The first function is a function of a single argument, which must be provided and can only validly take the value null
. Any value other than null will not compile. The second function doesn't take any argument and passing null
to it would not compile.