getclass - java reflection invoke method
¿Es el vacío realmente insostenible? (3)
Hacer que su constructor sea privado, y no tener ningún otro constructor al que se pueda acceder desde fuera, hace que una clase no pueda ser instanciada .
Sin embargo, no puede evitar que se acceda a él mediante la Reflection API
. Usando la reflexión, puedes hacer, lo que normalmente no está permitido.
Pero, si realmente quieres que tu clase sea ininstalable , incluso a través de Reflection , puedes throw
una Excepción no verificada desde el constructor .
private MyClass() {
throw UnsupportedOperationException("Can''t instantiate class");
}
En cuyo caso, cuando cree la instancia utilizando el método Constructor#newInstance()
, lanzará una InvocationTargetException
, como se cita en los comentarios de @Alex.
Aquí está la documentación del método Constructor#newInstance()
, que declara que se lanza una lista de excepciones, una de ellas es InvocationTargetException
, y dice que:
tiros
InvocationTargetException: si el constructor subyacente lanza una excepción.
El javadoc para Void
dice:
La clase Void es una clase de marcador de posición que no se puede sostener para mantener una referencia al objeto Class que representa el vacío de la palabra clave Java.
pero el constructor es simplemente:
private Void() {}
y este código crea una instancia de un Void
:
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor
Así que el Void
no es ininstalable.
¿Hubiera existido una manera de hacer que el Void
realmente ininstalable?
La API de Reflexión rompe todo tipo de "reglas" como esta, al igual que poder modificar final
campos final
. Hay muchas quejas sobre el hecho de que te permite romper las reglas duras y rápidas de Java, pero así es como es.
Sin Reflexión (o la API Unsafe
@ StevenSchlansker publicada a continuación), no es posible crear una instancia. Sin embargo, mientras se permita la Reflexión, estas soluciones alternativas existirán.
En el propio tutorial de Reflection de Oracle , enumeran los beneficios e inconvenientes. Depende de usted decidir cuál es mayor.
Además, vea esta pregunta: ¿Qué es la reflexión y por qué es útil?
Rohit tiene toda la razón de que lanzar una excepción es "lo suficientemente bueno" para la mayoría de los casos de uso. Sin embargo, parece que podría pasar por alto incluso eso, usando sun.misc.Unsafe :
La Asignación de Objeto nativa pública (Clase cls) lanza InstantiationException
Asigne una instancia pero no ejecute ningún constructor. Inicializa la clase si aún no ha sido.
(Tenga en cuenta que en realidad no he probado que esto funciona)