63

I have a class which defines two overloaded methods

public void handle(Void e) 

protected void handle() 

Obviously they are different, especially handle(Void e) is public.


What's the difference between those two?

How to call the first method? I am using handle(null) - is this correct?

Bohemian
  • 365,064
  • 84
  • 522
  • 658
Adam Lee
  • 21,598
  • 43
  • 138
  • 208

4 Answers4

68

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.

Bohemian
  • 365,064
  • 84
  • 522
  • 658
  • 8
    It does not mean "don't care about the type" it means "I want to return nothing but generics do not support `void` since it is not a class so I use `Void` instead". – josefx Dec 25 '12 at 16:48
  • 1
    +1 I believe you can instantiate an instance of `Void` by Reflection. – Eng.Fouad Dec 25 '12 at 17:00
  • 2
    @Adam this may sound like a strange request, but would you Ming accepting another answer? The reason is I would get a special "hat" if one of my answers outscores the accepted one. It would be a nice Xmas present :) - Thanks – Bohemian Dec 25 '12 at 20:07
  • @Adam that should have been *mind*, not Ming :) That's iPhone's auto correction crapnology for you... :/ – Bohemian Dec 25 '12 at 21:30
  • I have used `Void`, perhaps *unconventionally*, to resolve conflicts when expanding methods with more parameters (don't ask why). If `methodA(String)` needs to be expanded to `methodA(String, String)`, but `methodA(String, String)` already exists with a different meaning, I'd expand the first method as `methodA(String, Void, String)` (and call it as `methodA(strA, (Void)null, strB)`). Sure I can make it `methodB(String, String)`, but sometimes, not. (Again, don't ask why!) – ADTC Jul 23 '14 at 10:55
  • @ADTC I would just make it `methodB(String, String)` – Bohemian Jul 23 '14 at 13:16
  • I would too, but sometimes can't. Don't ask why. `:/` (Perks of working on large corporate systems.) – ADTC Jul 23 '14 at 13:26
  • Helpful answer. Although, early in the Answer you say "usually used only for reflection" and then later you say "usefully used as a generic parameter type". I have also seen this latter use - doesn't this contradict what you say earlier about it being used only for reflection (albeit qualified as usually)? – flow2k Oct 24 '17 at 20:50
46

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.

Martin Vseticka
  • 25,160
  • 25
  • 118
  • 187
Confusion
  • 14,331
  • 7
  • 43
  • 71
15

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.

Raffaele
  • 19,761
  • 5
  • 42
  • 81
  • The `Void ...` is needed to preserve argument count so `onProgressUpdate` properly overrides the same method in the parent (since in java, not passing an argument to this would cause it to become a new function rather than an override). – Zags Oct 29 '14 at 02:06
6

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.

Marko Topolnik
  • 179,046
  • 25
  • 276
  • 399