Java Void type - possible / valid values?

1) In Java, I can do this:

Void z = null; 

Is there any other value besides null I can assign z ?

2) Consider the following code:

 Callable<Void> v = () -> { System.out.println("zzz"); Thread.sleep(1000); return null; }; 

This compiles OK, but if I delete the last statement return null; , this is not true. What for? After all, Void does not mean any return value.

+5
source share
5 answers

From docs :

The Void class is an uninteresting placeholder class to reference a class object that represents the void keyword.

So no .

Void used by methods that return an object but return nothing.

A nice example can be observed with some use of AsyncTask in Android, in cases where you do not need to return any objects after completing the task.

Then you extend AsyncTask<[your params type], [your progress type], Void> and return null in the onPostExecute override.

In most cases, you will not need this (for example, Runnable usually more suitable than Callable<Void> ).

In more detail the question:

But if I delete the returned null, it will not compile ?! What for?

... because a Void is still an object. However, it may be null .

If your method declares that it returns Void , you need to (explicitly) return null .

+8
source

If you check the sources:

 package java.lang; public final class Void { public static final Class<Void> TYPE = Class.getPrimitiveClass("void"); private Void() { } } 

Emptiness:

  • final class
  • has a private constructor.

Without using Reflection, it is impossible to assign a type reference, but null .

+3
source

In Java, I can do it Void z = null; Is there any other value (but null) that I can assign to z?

You can create your own Void instances. You can use Reflection or Unsafe to create them, and not that it is a good idea.

But if I delete the returned null, it will not compile ?! What for? In the end, Void should mean just that - a return type.

Java is case sensitive, which means that Boolean and Boolean NOT of the same type and are not Void and Void . Void is a conditional wrapper for Void , but otherwise it's just a class that you should not create.

+2
source

Perhaps what you are asking is Runnable or Consumer - some interface that has no return value. Void serves only to show that you cannot expect anything but zero. This is still just a class, not a keyword or something special. A class that cannot be created, so you need to return null.

+1
source

It took a lot of effort to develop a lambda expression to handle int/Integer , etc. indistinguishable, so int->Long will be compatible with Integer->long , etc.

It is possible (and desirable) to relate to void/Void similar way, see comments by Goetz and Forax . However, they did not have time to implement the idea for java8 :(

You can enter an adapter type that is ()->void and ()->void ; this may simplify your use case a bit, see http://bayou.io/release/0.9/javadoc/bayou/util/function/Callable_Void.html


If you have a method that accepts ()->void , it will not work well with ()->void lambdas. One way 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 the types of functional parameters is complicated ... The above example works because both accept a zero-arg function. If the function has nonzero arguments

  foo( Function<String,Void> f ) // String->Void foo( Consumer<String> f ) // String->void 

it confuses the compiler (and the programmer)

  foo( str->System.out.println(str) ); // which foo? foo( System.out::println ); // which foo? 

Given the implicit lambda str->expr , the compiler needs a target type to understand it. The type of target here is set by the type of the method parameter. If the method is overloaded, we need to first allow the method to be overloaded ... which usually depends on the type of argument (lambda) ... Therefore, you can understand why this is difficult.

(Zero-arg lambda is never implicit. All argument types are known because there are no arguments.)

There are provisions in the lambda specification to resolve the following cases:

  foo( str->{ System.out.println(str); } ); foo( str->{ System.out.println(str); return null; } ); 

You can argue that in the previous example

  foo( str->System.out.println(str) ); 

since println(str) returns void , the version of void clearly not suitable, so the compiler should be able to resolve it. However, remember that in order to know the value of println(str) , you must first enable the str type, that is, overloading the foo method must first be resolved ...

Although in this case str explicitly String . Unfortunately, the lambda designer decided not to allow this, arguing that it was too complicated. This is a serious flaw, which is why we cannot overload methods like Comparator

  comparing( T->U ) //comparing( T->int ) // overloading won't work well comparingInt ( T->int ) // use a diff method name instead 
+1
source

Source: https://habr.com/ru/post/1240617/


All Articles