There are two further aspects that need to be considered when following the recommendation in the Javadoc by replacing:
clz.newInstance()
with:
clz.getDeclaredConstructor().newInstance()
Firstly, Class#getDeclaredConstructor
may throw InvocationTargetException
or NoSuchMethodException
(both forms of ReflectiveOperationException
), where as Class#newInstance
throws InstantiationException
for these conditions.
As these are not types of RuntimeException
, they need to be explicitly handled, arguably by catching them and setting them as a cause for a (new) InstantiationException
that can be thrown, to preserve the signature for the calling code.
Secondly, Class#getDeclaredConstructor
can cause an additional "accessDeclaredMembers"
security check to be made (as well as the checkPackageAccess()
check that Class#newInstance
also makes).
Therefore, additional steps (such as the use of AccessController#doPrivileged
) may need to be taken to ensure the caller does not fail this additional check.
So, a method like this:
Object createInstance(Class clz)
throws InstantiationException, IllegalAccessException {
return clz.newInstance();
}
might, once correctly modified, look something more like this:
Object createInstance(Class<?> clz)
throws InstantiationException, IllegalAccessException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws InstantiationException, IllegalAccessException {
try {
return clz.getDeclaredConstructor().newInstance();
} catch (InvocationTargetException|NoSuchMethodException e) {
throw (InstantiationException)((new InstantiationException()).initCause(e));
}
}
});
} catch (PrivilegedActionException pae) {
Exception e = pae.getException();
if (e instanceof InstantiationException) throw (InstantiationException)e;
throw (IllegalAccessException)e;
}
}