Dominando la API Reflection de Java: Guía práctica con ejemplos de código
¿Qué es Reflection en Java?
Java Reflection es el proceso de analizar y modificar todas las capacidades de una clase en tiempo de ejecución. La API Reflection en Java se usa para manipular una clase y sus miembros, que incluyen campos, métodos, constructores, etc., en tiempo de ejecución.
Una ventaja de la API Reflection en Java es que puede manipular miembros privados de la clase también.
El paquete java.lang.reflect proporciona muchas clases para implementar reflection. Los métodos de la clase java.lang.Class se usan para recopilar los metadatos completos de una clase particular.
En este tutorial aprenderás-
- Qué es Reflection
- Clases en el paquete java.lang.reflect
- Métodos usados en java.lang.Class
- Cómo obtener información completa sobre una clase
- Ejemplo 1: Cómo obtener Metadatos de Clase
- Ejemplo 2: Cómo obtener Metadatos de Variable
- Ejemplo 3: Cómo obtener Metadatos de Método
- Ejemplo 4: Cómo obtener Metadatos de Constructores
Clases en el paquete java.lang.reflect
A continuación se muestra una lista de varias clases de Java en java.lang.package para implementar reflection-
- Field: Esta clase se usa para recopilar información declarativa como tipo de dato, modificador de acceso, nombre y valor de una variable.
- Method: Esta clase se usa para recopilar información declarativa como modificador de acceso, tipo de retorno, nombre, tipos de parámetros y tipo de excepción de un método.
- Constructor: Esta clase se usa para recopilar información declarativa como modificador de acceso, nombre y tipos de parámetros de un constructor.
- Modifier: Esta clase se usa para recopilar información sobre un modificador de acceso particular.
Métodos usados en java.lang.Class
- Public String getName(): Devuelve el nombre de la clase.
- public Class getSuperclass(): Devuelve la referencia de la superclase.
- Public Class[] getInterfaces(): Devuelve un array de interfaces implementadas por la clase especificada.
- Public int getModifiers(): Devuelve un valor entero que representa los modificadores de la clase especificada, que debe pasarse como parámetro al método public static String toString(int i) que devuelve el especificador de acceso para la clase dada.
Cómo obtener información completa sobre una clase
Para obtener información sobre variables, métodos y constructores de una clase, necesitamos crear un objeto de la clase.
public class Guru99ClassObjectCreation {
public static void main (String[] args) throws ClassNotFoundException {
//1 - Usando el método Class.forname()
Class c1 = Class.forName("Guru99ClassObjectCreation");
//2- Usando el método getClass()
Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
Class c2 = guru99Obj.getClass();
//3- Usando .class
Class c3= Guru99ClassObjectCreation.class;
}
}
Ejemplo 1: Cómo obtener Metadatos de Clase
El siguiente ejemplo muestra cómo obtener metadatos como: Nombre de la clase, nombre de la superclase, interfaces implementadas y modificadores de acceso de una clase.
Obtendremos los metadatos de la clase llamada Guru99Base.class:

import java.io.Serializable;
public abstract class Guru99Base implements Serializable,Cloneable {
}
- Nombre de la clase es: Guru99Base
- Sus modificadores de acceso son: public y abstract
- Ha implementado interfaces: Serializable y Cloneable
- Como no ha extendido ninguna clase explícitamente, su superclase es: java.lang.Object
La siguiente clase obtendrá los metadatos de Guru99Base.class e imprimirá:

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
public static void main (String [] args) throws ClassNotFoundException {
// Crear objeto Class para Guru99Base.class
Class<Guru99Base> guru99ClassObj = Guru99Base.class;
// Imprimir nombre de la clase
System.out.println("Nombre de la clase es: " + guru99ClassObj.getName());
// Imprimir nombre de la superclase
System.out.println("Nombre de la superclase es: " + guru99ClassObj.getSuperclass().getName());
// Obtener la lista de interfaces implementadas en forma de array Class usando getInterfaces()
Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();
// Imprimir las interfaces implementadas usando bucle foreach
System.out.print("Interfaces implementadas son: ");
for (Class guru99class1 : guru99InterfaceList) {
System.out.print(guru99class1.getName() + " ");
}
System.out.println();
// Obtener modificadores de acceso usando getModifiers() y toString() de java.lang.reflect.Modifier
int guru99AccessModifier = guru99ClassObj.getModifiers();
// Imprimir los modificadores de acceso
System.out.println("Modificadores de acceso de la clase son: " + Modifier.toString(guru99AccessModifier));
}
}
- Imprimir el nombre de la clase usando el método getName
- Imprimir el nombre de la superclase usando getSuperClass().getName()
- Imprimir el nombre de las interfaces implementadas
- Imprimir los modificadores de acceso usados por la clase


Ejemplo 2: Cómo obtener Metadatos de Variable
Los siguientes ejemplos muestran cómo obtener metadatos de variable:
Aquí, estamos creando una clase llamada Guru99VariableMetaData.class con algunas variables:
package guru;
public class Guru99VariableMetaData {
public static int guru99IntVar1=1111;
static int guru99IntVar2=2222;
static String guru99StringVar1="guru99.com";
static String guru99StringVar2="Learning Reflection API";
}
Pasos para obtener los metadatos sobre las variables en la clase anterior:
- Crear el objeto de clase de la clase anterior, es decir, Guru99VariableMetaData.class como se muestra:
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData(); Class guru99ClassObjVar = guru99ClassVar.getClass();
- Obtener los metadatos en forma de array de Field usando los métodos getFields() o getDeclaredFields():
Field[] guru99Field1 = guru99ClassObjVar.getFields(); Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();
getFields() devuelve metadatos de la variable pública de la clase especificada así como de su superclase.
getDeclaredFields() devuelve metadatos de todas las variables de la clase especificada solamente.
- Obtener el nombre de las variables usando el método "public String getName()".
- Obtener el tipo de dato de las variables usando "public Class getType()".
- Obtener el valor de la variable usando "public xxx get(Field)". Aquí, xxx podría ser byte, short o cualquier tipo de valor que queramos obtener.
- Obtener los modificadores de acceso de las variables usando getModifier() y Modifier.toString(int i).
Aquí, estamos escribiendo una clase para obtener los metadatos de las variables presentes en la clase Guru99VariableMetaData.class:

package guru;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Guru99VariableMetaDataTest {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
// Crear objeto Class para Guru99VariableMetaData.class
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();
// Obtener los metadatos de todos los campos de la clase Guru99VariableMetaData
Field[] guru99Field1 = guru99ClassObjVar.getDeclaredFields();
// Imprimir nombre, tipos de dato, modificadores de acceso y valores de las variables de la clase especificada
for(Field field : guru99Field1) {
System.out.println("Nombre de variable: " + field.getName());
System.out.println("Tipos de dato de la variable: " + field.getType());
int guru99AccessModifiers = field.getModifiers();
System.out.println("Modificadores de acceso de la variable: " + Modifier.toString(guru99AccessModifiers));
System.out.println("Valor de la variable: " + field.get(guru99ClassVar));
System.out.println();
System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
}
}
}
- Creado objeto de clase para Guru99VariableMetaData.class
- Obtenidos todos los metadatos de las variables en un array Field
- Imprimidos todos los nombres de variables en la clase Guru99VariableMetaData.class
- Imprimidos todos los tipos de dato de las variables en la clase Guru99VariableMetaData.class
- Imprimidos todos los modificadores de acceso de las variables en la clase Guru99VariableMetaData.class
- Imprimidos valores de todas las variables en la clase Guru99VariableMetaData.class


Ejemplo 3: Cómo obtener Metadatos de Método
Los siguientes ejemplos muestran cómo obtener metadatos de un método:
Aquí, estamos creando una clase llamada Guru99MethodMetaData.class con algunos métodos:

package guru;
import java.sql.SQLException;
public class Guru99MethodMetaData {
public void guru99Add(int firstElement, int secondElement, String result) throws ClassNotFoundException, ClassCastException {
System.out.println("Método demo para Reflection API");
}
public String guru99Search(String searchString) throws ArithmeticException, InterruptedException {
System.out.println("Método demo para Reflection API");
return null;
}
public void guru99Delete(String deleteString) throws SQLException {
System.out.println("Método demo para Reflection API");
}
}
Pasos para obtener los metadatos sobre los métodos en la clase anterior:
- Crear el objeto de clase de la clase anterior, es decir, Guru99MethodMetaData.class:
Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData(); Class guru99ClassObjVar = guru99ClassVar.getClass();
- Obtener información del método en un array Method usando getMethods() y getDeclaredMethods():
Method[] guru99Method1 = guru99ClassObjVar.getMethods(); Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();
getMethods() devuelve metadatos de los métodos públicos de la clase especificada y de su superclase.
getDeclaredMethods() devuelve metadatos de todos los métodos de la clase especificada solamente.
- Obtener el nombre del método usando getName().
- Obtener el tipo de retorno del método usando getReturnType().
- Obtener modificadores de acceso de los métodos usando getModifiers() y Modifier.toString(int i).
- Obtener tipos de parámetros del método usando getParameterTypes() que devuelve un array de Class.
- Obtener excepciones lanzadas usando getExceptionTypes() que devuelve un array de Class.
Aquí, escribimos una clase para obtener los metadatos de los métodos presentes en la clase Guru99MethodMetaData.class:

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Guru99MethodMetaDataTest {
public static void main(String[] args) {
// Crear objeto Class para Guru99MethodMetaData.class
Class guru99ClassObj = Guru99MethodMetaData.class;
// Obtener los metadatos de todos los métodos de la clase usando getDeclaredMethods()
Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();
for(Method method : guru99Methods) {
// Imprimir nombres de métodos
System.out.println("Nombre del método: " + method.getName());
// Imprimir tipo de retorno de los métodos
System.out.println("Tipo de retorno del método: " + method.getReturnType());
// Obtener lista de modificadores de acceso e imprimir
int guru99ModifierList = method.getModifiers();
System.out.println("Modificadores de acceso del método: " + Modifier.toString(guru99ModifierList));
// Obtener e imprimir parámetros de los métodos
Class[] guru99ParamList = method.getParameterTypes();
System.out.print("Tipos de parámetros del método: ");
for (Class class1 : guru99ParamList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
// Obtener e imprimir excepciones lanzadas por el método
Class[] guru99ExceptionList = method.getExceptionTypes();
System.out.print("Excepciones lanzadas por el método: ");
for (Class class1 : guru99ExceptionList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
}
}
}
- Creado objeto de clase para Guru99MethodMetaData.class
- Obtenidos todos los metadatos de todos los métodos en un array Method
- Imprimidos todos los nombres de métodos presentes en la clase Guru99MethodMetaData.class
- Imprimidos tipos de retorno de los métodos en la clase Guru99MethodMetaData.class
- Imprimidos todos los modificadores de acceso de los métodos en la clase Guru99MethodMetaData.class
- Imprimidos tipos de parámetros de los métodos en Guru99MethodMetaData.class
- Imprimidas excepciones lanzadas por métodos en Guru99MethodMetaData.class


Ejemplo 4: Cómo obtener Metadatos de Constructores
Los siguientes ejemplos muestran cómo obtener metadatos de constructores:
Aquí, estamos creando una clase llamada Guru99Constructor.class con diferentes constructores:

package guru;
import java.rmi.RemoteException;
import java.sql.SQLException;
public class Guru99Constructor {
public Guru99Constructor(int no) throws ClassCastException, ArithmeticException {
}
public Guru99Constructor(int no, String name) throws RemoteException, SQLException {
}
public Guru99Constructor(int no, String name, String address) throws InterruptedException {
}
}
Aquí, escribimos una clase para obtener los metadatos de los constructores presentes en la clase Guru99Constructor.class:

package guru;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Guru99ConstructorMetaDataTest {
public static void main(String[] args) {
// Crear objeto Class para Guru99Constructor.class
Class guru99Class = Guru99Constructor.class;
// Obtener toda la información de constructores en el array Constructor
Constructor[] guru99ConstructorList = guru99Class.getConstructors();
for (Constructor constructor : guru99ConstructorList) {
// Imprimir nombre de cada constructor
System.out.println("Nombre del constructor: " + constructor.getName());
// Obtener e imprimir modificadores de acceso de cada constructor
int guru99Modifiers = constructor.getModifiers();
System.out.println("Modificador del constructor: " + Modifier.toString(guru99Modifiers));
// Obtener e imprimir tipos de parámetros
Class[] guru99ParamList = constructor.getParameterTypes();
System.out.print("Tipos de parámetros del constructor: ");
for (Class class1 : guru99ParamList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
// Obtener e imprimir excepciones lanzadas por constructores
Class[] guru99ExceptionList = constructor.getExceptionTypes();
System.out.println("Excepciones lanzadas por constructores: ");
for (Class class1 : guru99ExceptionList) {
System.out.print(class1.getName() + " ");
}
System.out.println();
System.out.println("*******************************************");
}
}
}
- Creado objeto de clase para Guru99Constructor.class
- Obtenidos todos los metadatos de todos los constructores en un array Constructor
- Imprimidos todos los nombres de constructores presentes en la clase Guru99Constructor.class
- Imprimidos todos los modificadores de acceso de los constructores en la clase Guru99Constructor.class
- Imprimidos tipos de parámetros de los constructores en Guru99Constructor.class
- Imprimidas excepciones lanzadas por constructores en Guru99Constructor.class


Resumen:
- La programación Reflection en Java ayuda a recuperar y modificar información sobre Clases y miembros de Clase como variables, métodos, constructores.
- La API Reflection en Java se puede implementar usando clases en el paquete java.lang.reflect y métodos de la clase java.lang.Class.
- Métodos comúnmente usados de java.lang.Class: getName(), getSuperclass(), getInterfaces(), getModifiers(), etc.
- Clases comúnmente usadas en java.lang.reflect: Field, Method, Constructor, Modifier, etc.
- La API Reflection puede acceder a métodos y variables privadas de una clase, lo que podría ser una amenaza de seguridad.
- La API Reflection es una capacidad poderosa proporcionada por Java, pero conlleva sobrecostes como rendimiento más lento, vulnerabilidad de seguridad y problemas de permisos. Por tanto, la API Reflection debe tratarse como último recurso para realizar una operación.
Java
- Clases y objetos en C++: Guía práctica con ejemplos de código
- Dominando Clases y Objetos en C#: Tutorial Práctico con Ejemplos Reales
- Clases Abstractas en C#: Tutorial Práctico con Ejemplos de Código
- Dominando las clases internas anónimas en Java: Definición, sintaxis y ejemplos prácticos
- Dominando la Reflexión en Java: Inspeccionando clases, métodos y campos en tiempo de ejecución
- Dominando ObjectInputStream de Java: Guía Completa
- Dominando ObjectOutputStream de Java: Serialización, Métodos y Ejemplos Prácticos
- Entendiendo Java String.charAt(): Sintaxis, tipo de retorno, excepciones y ejemplo práctico
- Dominando Java String.endsWith(): Cómo comprobar sufijos de cadena con ejemplos
- Lectura de archivos en Java con BufferedReader – Guía práctica con ejemplos
- Algoritmo Insertion Sort en Java: Ejemplo Claro y Guía Paso a Paso