The javadoc for Void
says:
The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void.
but the constructor is simply:
private Void() {}
and this code instantiates a Void
:
Constructor<Void> c = Void.class.getDeclaredConstructor(); c.setAccessible(true); Void v = c.newInstance(); // Hello sailor
So Void
is not uninstantiable.
Would there have been a way to make Void
truly uninstantiable?
The basic difference between both ( Void & void ) is that void is a primitive type while Void , a reference type that inherits from the Object . Although none of them has any possible values, both are of different types. The void (all lowercase) is the improper type used to refer to the value's absence.
Generics. As shown above, in order to return from a method with the Void return type, we just have to return null. Moreover, we could have either used a random type (such as Callable<Integer>) and return null or no type at all (Callable), but using Void states our intentions clearly.
You declare a method's return type in its method declaration. Within the body of the method, you use the return statement to return the value. Any method declared void doesn't return a value. It does not need to contain a return statement, but it may do so.
Rohit is quite right that throwing an exception is "good enough" for most use cases. However, it looks like it might be possible to bypass even that, using sun.misc.Unsafe:
public native Object allocateInstance(Class cls) throws InstantiationException
Allocate an instance but do not run any constructor. Initializes the class if it has not yet been.
(Note that I haven't actually tested that this works)
Making your constructor private, and not having any other constructor that can be accessed by outside, makes a class un-instantiable.
However, you cannot avoid it from being accessed using Reflection API
. Using reflection, you can do, what is not allowed normally.
But, if you really want your class to be uninstantiable, even through Reflection, you can throw
an Unchecked Exception from the constructor.
private MyClass() { throw UnsupportedOperationException("Can't instantiate class"); }
In which case, when you create the instance using Constructor#newInstance()
method, it will throw an InvocationTargetException
, as quoted in comments by @Alex.
Here's the documentation of Constructor#newInstance()
method, which declares a list of exception to be thrown, one of them is InvocationTargetException
, and it says that: -
throws:
InvocationTargetException - if the underlying constructor throws an exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With