Java Tutorial de API de reflexión con ejemplo

⚡ Resumen inteligente

Java La API Reflection analiza y modifica las capacidades de una clase en tiempo de ejecución, incluyendo sus campos, métodos y constructores. Este recurso explica el paquete java.lang.reflect, los métodos clave de java.lang.Class y cuatro ejemplos que leen los metadatos de una clase, variable, método y constructor.

  • 🔍 Definición: La reflexión inspecciona y modifica las clases y sus miembros en tiempo de ejecución, incluso los privados.
  • 📦 Paquete Reflect: Las clases Campo, Método, Constructor y Modificador recopilan información declarativa sobre los miembros.
  • 🏷️ Métodos de clase: Las funciones getName(), getSuperclass(), getInterfaces() y getModifiers() devuelven metadatos de la clase principal.
  • 🧪 Ejemplos resueltos: Cuatro programas extracmetadatos de una clase, variables, métodos y constructores.
  • ⚠️ Precaución: Reflection puede acceder a miembros privados y es más lento, así que úselo como último recurso.

Java Tutorial de la API de reflexión

¿Qué es la reflexión en Java?

Java La reflexión es el proceso de analizar y modificar todas las capacidades de una clase en tiempo de ejecución. La API de reflexión en Java Se utiliza para manipular una clase y sus miembros, que incluyen campos, métodos, constructores, etc., en tiempo de ejecución.

Una ventaja de la API de reflexión en Java Es que también puede manipular a los miembros privados de la clase.

El paquete java.lang.reflect proporciona numerosas clases para implementar la reflexión. Los métodos de la clase java.lang.Class se utilizan para recopilar los metadatos completos de una clase específica.

Clase en el paquete java.lang.reflect

A continuación se muestra una lista de diversos Java privadas en el paquete java.lang.reflect para implementar la reflexión:

  • Campo: Esta clase se utiliza para recopilar información declarativa, como el tipo de datos, el modificador de acceso, el nombre y el valor de una variable.
  • Método: Esta clase se utiliza para recopilar información declarativa, como el modificador de acceso, el tipo de retorno, el nombre, los tipos de parámetros y el tipo de excepción de un método.
  • Constructor: Esta clase se utiliza para recopilar información declarativa, como el modificador de acceso, el nombre y los tipos de parámetros de un constructor.
  • Modificador: Esta clase se utiliza para recopilar información sobre un modificador de acceso específico.

Métodos utilizados en java.lang.Class

  • public String getName(): Devuelve el nombre de la clase.
  • Clase pública obtenerSuperclase(): Devuelve la referencia de la superclase.
  • public Class[] getInterfaces(): Devuelve una matriz de interfaces implementadas por la clase especificada.
  • público entero obtenerModificadores(): 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 las variablesPara crear un objeto de una clase, necesitamos usar sus métodos y constructores. El siguiente ejemplo muestra diferentes maneras de crear un objeto de la clase “Class”:

Métodos utilizados en java.lang.Class

public class Guru99ClassObjectCreation {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1 - By using Class.forName() method
        Class c1 = Class.forName("Guru99ClassObjectCreation");
        // 2 - By using getClass() method
        Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
        Class c2 = guru99Obj.getClass();
        // 3 - By using .class
        Class c3 = Guru99ClassObjectCreation.class;
    }
}

Ejemplo 1: Cómo obtener los metadatos de una clase

El siguiente ejemplo muestra cómo obtener metadatos como el nombre de la clase, el nombre de la superclase, las interfaces implementadas y los modificadores de acceso de una clase.

Obtendremos los metadatos de la siguiente clase llamada Guru99Base.class:

Obtener metadatos de clase

import java.io.Serializable;
public abstract class Guru99Base implements Serializable, Cloneable {
}
  1. El nombre de la clase es: Guru99 base
  2. Sus modificadores de acceso son: public y abstract
  3. Tiene interfaces implementadas: Serializable y Clonable.
  4. Dado que no ha extendido explícitamente ninguna clase, su superclase es: java.lang.Object

La siguiente clase obtendrá los metadatos de Guru99Base.class e imprímelo:

Obtener metadatos de clase

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
    public static void main(String[] args) throws ClassNotFoundException {
        // Create Class object for Guru99Base.class
        Class<Guru99Base> guru99ClassObj = Guru99Base.class;

        // Print name of the class
        System.out.println("Name of the class is : " + guru99ClassObj.getName());

        // Print super class name
        System.out.println("Name of the super class is : " + guru99ClassObj.getSuperclass().getName());

        // Get the list of implemented interfaces using getInterfaces() method
        Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();

        // Print the implemented interfaces using a for-each loop
        System.out.print("Implemented interfaces are : ");
        for (Class guru99class1 : guru99InterfaceList) {
            System.out.print(guru99class1.getName() + " ");
        }
        System.out.println();

        // Get access modifiers using getModifiers() and Modifier.toString()
        int guru99AccessModifier = guru99ClassObj.getModifiers();
        System.out.println("Access modifiers of the class are : " + Modifier.toString(guru99AccessModifier));
    }
}
  1. Imprime el nombre de la clase usando el método getName().
  2. Imprime el nombre de la superclase usando el método getSuperclass().getName().
  3. Imprime los nombres de las interfaces implementadas.
  4. Imprime los modificadores de acceso utilizados por la clase.

Obtener metadatos de clase

Obtener metadatos de clase

Ejemplo 2: Cómo obtener los metadatos de una variable

El siguiente ejemplo muestra cómo obtener los metadatos de una 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 de la clase anterior:

  1. Crea el objeto de clase de la clase anterior, es decir, Guru99VariableMetaData.class, como se muestra a continuación:
    Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Obtenga los metadatos en forma de matriz de campos utilizando el getFields () or obtenerCamposDeclarados() métodos de la siguiente manera:
    Field[] guru99Field1 = guru99ClassObjVar.getFields();
    Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();

El getFields () Este método devuelve los metadatos de las variables públicas de la clase especificada, así como de su superclase.

El obtenerCamposDeclarados() Este método devuelve únicamente los metadatos de todas las variables de la clase especificada.

  1. Obtén el nombre de las variables usando el método “public String getName()”.
  2. Obtén el tipo de datos de las variables usando el método “public Class getType()”.
  3. Obtén el valor de la variable usando el método “public xxx get(Field)”. Aquí, xxx puede ser un byte, un valor corto o cualquier otro tipo de valor que queramos obtener.
  4. Obtenga los modificadores de acceso de las variables utilizando los métodos getModifiers() y Modifier.toString(int i).

Aquí, estamos escribiendo una clase para obtener los metadatos de las variables presentes en la clase. Guru99VariableMetaData.class:

Obtener metadatos de variable

package guru;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Guru99VariableMetaDataTest {
    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
        // Create Class object for Guru99VariableMetaData.class
        Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
        Class guru99ClassObjVar = guru99ClassVar.getClass();

        // Get the metadata of all the fields of the class
        Field[] guru99Field1 = guru99ClassObjVar.getDeclaredFields();

        // Print name, data types, access modifiers and values of the variables
        for (Field field : guru99Field1) {
            System.out.println("Variable name : " + field.getName());
            System.out.println("Datatype of the variable : " + field.getType());

            int guru99AccessModifiers = field.getModifiers();
            System.out.println("Access Modifiers of the variable : " + Modifier.toString(guru99AccessModifiers));
            System.out.println("Value of the variable : " + field.get(guru99ClassVar));
            System.out.println();
        }
    }
}
  1. Se creó un objeto de clase para Guru99VariableMetaData.class.
  2. Obtuve todos los metadatos de las variables en una matriz Field.
  3. Imprimió todos los nombres de las variables en la clase. Guru99VariableMetaData.class.
  4. Se imprimieron todos los tipos de datos de las variables de la clase.
  5. Se imprimieron todos los modificadores de acceso de las variables de la clase.
  6. Se imprimieron los valores de todas las variables de la clase.

Obtener metadatos del método

Obtener metadatos del método

Ejemplo 3: Cómo obtener los metadatos del método

El siguiente ejemplo muestra cómo obtener los metadatos de un método.

Aquí estamos creando una clase llamada Guru99MethodMetaData.class con algunos métodos:

Obtener metadatos del método

package guru;
import java.sql.SQLException;
public class Guru99MethodMetaData {

    public void guru99Add(int firstElement, int secondElement, String result)
    throws ClassNotFoundException, ClassCastException {
        System.out.println("Demo method for Reflection API");
    }
    public String guru99Search(String searchString)
    throws ArithmeticException, InterruptedException {
        System.out.println("Demo method for Reflection API");
        return null;
    }
    public void guru99Delete(String deleteString)
    throws SQLException {
        System.out.println("Demo method for Reflection API");
    }
}

Pasos para obtener los metadatos sobre los métodos de la clase anterior:

  1. Crea el objeto de clase de la clase anterior, es decir, Guru99MethodMetaData.class, como se muestra a continuación:
    Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Obtenga información sobre los métodos en una matriz Method utilizando los métodos getMethods() y getDeclaredMethods() como se muestra a continuación:
    Method[] guru99Method1 = guru99ClassObjVar.getMethods();
    Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();

    El obtener métodos() El método devuelve los metadatos de los métodos públicos de la clase especificada, así como de su superclase. obtener métodos declarados () Este método devuelve únicamente los metadatos de todos los métodos de la clase especificada.

  3. Obtenga el nombre del método usando el getName () método.
  4. Obtenga el tipo de retorno del método usando el getReturnType() método.
  5. Obtenga los modificadores de acceso de los métodos utilizando el getModifiers () y Modificador.toString(int i) métodos.
  6. Obtenga los tipos de parámetros del método usando el getParameterTypes () método, que devuelve un array de clase.
  7. Obtener excepciones lanzadas usando el obtener tipos de excepción() método, que devuelve un array de clase.

Aquí, estamos escribiendo una clase para obtener los metadatos de los métodos presentes en la clase. Guru99MethodMetaData.class:

Obtener metadatos del método

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99MethodMetaData.class
        Class guru99ClassObj = Guru99MethodMetaData.class;

        // Get the metadata of all the methods using getDeclaredMethods()
        Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();

        for (Method method : guru99Methods) {
            System.out.println("Name of the method : " + method.getName());
            System.out.println("Return type of the method : " + method.getReturnType());

            int guru99ModifierList = method.getModifiers();
            System.out.println("Method access modifiers : " + Modifier.toString(guru99ModifierList));

            Class[] guru99ParamList = method.getParameterTypes();
            System.out.print("Method parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = method.getExceptionTypes();
            System.out.print("Exception thrown by method : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Se creó un objeto de clase para Guru99MethodMetaData.class.
  2. Obtuve todos los metadatos de todos los métodos en un array de métodos.
  3. Se imprimieron todos los nombres de los métodos presentes en la clase.
  4. Se imprimieron los tipos de retorno de los métodos de la clase.
  5. Se imprimieron todos los modificadores de acceso de los métodos de la clase.
  6. Se imprimieron los tipos de parámetros de los métodos.
  7. Se imprimieron las excepciones generadas por los métodos.

Obtener metadatos del método

Obtener metadatos del método

Ejemplo 4: Cómo obtener metadatos de los constructores

El siguiente ejemplo muestra cómo obtener los metadatos de los constructores.

Aquí estamos creando una clase llamada Guru99Constructor.class con diferentes constructores:

Obtener metadatos de 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í, estamos escribiendo una clase para obtener los metadatos de los constructores presentes en la clase. Guru99Constructor.class:

Obtener metadatos de constructores

package guru;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Guru99ConstructorMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99Constructor.class
        Class guru99Class = Guru99Constructor.class;

        // Get all the constructor information in the Constructor array
        Constructor[] guru99ConstructorList = guru99Class.getConstructors();

        for (Constructor constructor : guru99ConstructorList) {
            System.out.println("Constructor name : " + constructor.getName());

            int guru99Modifiers = constructor.getModifiers();
            System.out.println("Constructor modifier : " + Modifier.toString(guru99Modifiers));

            Class[] guru99ParamList = constructor.getParameterTypes();
            System.out.print("Constructor parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = constructor.getExceptionTypes();
            System.out.print("Exception thrown by constructors : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Se creó un objeto de clase para Guru99Constructor.class.
  2. Obtuve todos los metadatos de todos los constructores en un array de constructores.
  3. Se imprimieron todos los nombres de los constructores presentes en la clase.
  4. Se imprimieron todos los modificadores de acceso de los constructores de la clase.
  5. Se imprimieron los tipos de parámetros de los constructores.
  6. Se imprimieron las excepciones lanzadas por los constructores.

Obtener metadatos de constructores

Obtener metadatos de constructores

Preguntas Frecuentes

La reflexión permite que los frameworks y las herramientas de IA inspeccionen e instancien clases en tiempo de ejecución. Impulsa la inyección de dependencias, la serialización y el mapeo ORM.pingy la carga dinámica de complementos sin conocer las clases exactas en tiempo de compilación.

La IA puede generar código de reflexión rápidamente, pero es necesario revisarlo cuidadosamente. La reflexión puede eludir las comprobaciones de acceso e introducir riesgos de seguridad y rendimiento, por lo que el código generado necesita ser probado y validado.

La reflexión es más lenta que las llamadas directas a métodos, puede romper el encapsulamiento al acceder a miembros privados y puede causar problemas de seguridad y mantenimiento. Solo debe usarse cuando no haya una alternativa más sencilla.

Sí. Al usar setAccessible(true), la reflexión puede leer y modificar campos privados e invocar métodos privados. Esto es muy útil para pruebas y frameworks, pero puede romper la encapsulación y generar problemas de seguridad.

Resumir este post con: