I know that an instance of a class with a private constructor can be created using reflection but is there any way to make sure that the instance of the class can only be created within the same class using its own private constructor?
Let's take an example of a class Test, with a private constructor.
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Test
{
private Test() //private constructor
{
}
}
public class Sample{
public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{
Class c=Class.forName("Test"); //specify class name in quotes
//----Accessing private constructor
Constructor con=c.getDeclaredConstructor();
con.setAccessible(true);
Object obj=con.newInstance();
}
}
My question is - is there any way to ensure that the instance of the class can only be created within the same class and not from outside using reflection or any other method?
There are several ways to prevent the creation - but it is hard to tell which one is appropriate for your use-case:
Throw an exception in the constructor
You can either unconditionally throw an exception - making it (near) impossible to instantiate an instance - or only throw under certain conditions.
Some conditions can be:
StackWalker
for example.Use Java Modules.
As other modules can't deeply reflect into other named modules, Constructor.setAccessible
will not work on your class outside of your own module.
Of course this restriction doesn't apply to your own module - but you should be able to control your own module ;).
Install a SecurityManager
.
Prevents Constructor.setAccessible
from returning successfully.
But the security manager is deprecated for removal, so I can't recommend it's use.
Note: Most of those solutions can be circumvented in some way. And it is sometimes possible to add additional defenses against that. But at the end, it'll become a game of cat and mouse.