A lot of efforts were spent in designing lambda expression to treat int/Integer etc indistinguishably, so that int->Long will be compatible with Integer->long, etc.
It is possible (and desirable) to treat void/Void in a similar way, see comments from Goetz and Forax.
However, they didn't have the time to implement the idea for java8 :(
You can introduce an adapter type that is both ()->void and ()->Void; it can simplify your use case a little bit, see http://bayou.io/release/0.9/javadoc/bayou/util/function/Callable_Void.html
If you have a method that accepts ()->Void, it is not going to work well with ()->void lambdas. One workaround is to overload the method to accept ()->void. For example, ExecutorService
submit(Callable<T> task)
submit(Runnable task)
...
submit( System::gc ); // ()->void
However, overloading with functional parameter types is tricky... The example above works because both accept a zero-arg function. If the function has non-zero args
foo( Function<String,Void> f ) // String->Void
foo( Consumer<String> f ) // String->void
it's confusing to the compiler (and the programmer)
foo( str->System.out.println(str) ); // which foo?
foo( System.out::println ); // which foo?
Given an implicit lambda str->expr, the compiler needs a target type to make sense of it. The target type here is given by the method parameter type. If the method is overloaded, we need to resolve method overloading first... which typically depends on the type of the argument (the lambda)... So you can see why it is complicated.
(A zero-arg lambda is never implicit. All argument types are known, since there's no argument.)
The lambda spec does have provisions to resolve the following cases
foo( str->{ System.out.println(str); } );
foo( str->{ System.out.println(str); return null; } );
You may argue that in the previous example,
foo( str->System.out.println(str) );
since println(str) returns void, the Void version obviously does not fit, therefore the compiler should be able to resolve it. However, remember that, to know the meaning of println(str), first, the type of str must be resolved, i.e. method overloading of foo must be resolved first...
Although in this case, str is unambiguously String. Unfortunately, the lambda designer decided against to be able to resolve that, arguing it is too complicated. This is a serious flaw, and it is why we cannot overload methods like in Comparator
comparing( T->U )
//comparing( T->int ) // overloading won't work well
comparingInt ( T->int ) // use a diff method name instead
nullIS A value, it's just a special value. Returning null and not returning anything are different things.