Reglas de Reflexión != Reglas de No Reflexión

Lo que el compilador de Java conoce es diferente de lo que conoce el run time.
Esa diferencia se debe a varias cosas, entre ellas al “desconocimiento” que la máquina virtual tiene de “cosas” que el compilador sí conoce.
En ocasiones suceden cosas “extrañas”.
Es el caso de algunas diferencias importantes entre el código “normal” y el código que hace uso de reflexión.

A continuación algunos ejemplos de algunas de esas diferencias.

Ejemplo 1
La firma (signature) de los constructores de las clases inner son “distintas” para el compilador y para el run time. La máquina virtual “no sabe nada de clases inner”. La unidad de distribución de código en Java es la clase.

El código:
 

El código hace lo siguiente:

  1. Define la clase pública Main, una clase Outer, una clase Inner y una clase Nested.
  2. La clase Main incluye un pequeño programa que crea un objeto de clase Outer, un objeto de clase Inner y un objeto de clase Nested.
  3. Esos objetos se crean con código sin reflexión y con código con reflexión.
  4. Para el código sin reflexión creamos los objetos de clase Inner y de clase Nested con el constructor que el compilador ve. El compilador “sabe” que la clase Inner es una clase inner definida dentro de Outer y que Nested es una clase anidada definida también dentro de Outer. Distingo aquí las clases anidadas de las clases inner o interiores, porque son distintas.
  5. Para el código con reflexión obtengo primero el objeto Constructor para ambas clases, la clase Inner y la clase Outer. La sentencia
     
    de manera “inocente”, considera que el constructor de la clase Inner tiene la firma   y consecuentemente obtiene el objeto Constructor con la sentencia anterior.
  6. La sentencia
     
    sabe que la máquina virtual desconoce que Inner es una clase interior de Outer, y entonces pide el constructor real que Inner tiene con la firma  . Una vez que un objeto de clase Inner(el objeto innerObject) se crea, está “atado” a un objeto de clase Outer (el objeto outerObject).
  7. Para la clase anidada Nested, tanto el compilador como la máquina virtual “ven” el mismo constructor con la firma  . No hay atadura entre los objetos outerObject y nestedObject en el programa.
  8. Al correr el programa se disparará la excepción
     
    producida por la sentencia
     
    Es lógico; ese constructor no existe aunque así lo escribimos en la clase Inner.
  9. Para ejecutar el programa, es necesario comentar o eliminar las sentencias incorrectas:
     

Moraleja
La firma de los constructores de clases internas no es la que escribimos para esas clases. Añade a la lista de sus argumentos como primer parámetro, una referencia a su clase Outer si deseas construir objetos mediante reflexión.

Ejemplo 2
Las reglas de acceso a métodos públicos de clases no públicas son diferentes con reflexión y sin reflexión
Pero ya es muy largo este post. Lo dejo para el siguiente.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Que tal bferro. Me gusta el

Que tal bferro.

Me gusta el tema, pero me costó un poco de trabajo seguir el hilo de lo que escribiste. Quizá sería más fácil de seguir si los comentarios estuvieran en el código, así no tendría que saltar hacia atrás y hacia adelante.

Por ejemplo, un comentario muy útil sería saber donde empieza el código normal y donde el código usando reflexión, puede parecer obvio cuando ya lo sabes, pero no lo es.

Saludos.

Imagen de bferro

Código comentado (Reglas de Reflexión != Reglas de No Reflexión)

Gracias OscarRyz por la sugerencia.
Ya quedó el código comentado