CodeGym /Cursos /JAVA 25 SELF /Obtención de información sobre clases, campos y métodos

Obtención de información sobre clases, campos y métodos

JAVA 25 SELF
Nivel 62, Lección 1
Disponible

1. Obtención de información sobre los campos

En qué se diferencian getFields() y getDeclaredFields()

En Java, cada clase tiene campos (fields): variables declaradas dentro de la clase. Con reflexión podemos conocer sus nombres, tipos, modificadores de acceso (public/private) y también acceder a ellos en tiempo de ejecución. La entrada principal es el objeto Class<?>.

Métodos principales de la clase Class para trabajar con campos:

Método Qué devuelve
getFields()
Array de todos los campos public de la clase, sus padres e interfaces
getDeclaredFields()
Array de todos los campos declarados en esta clase

Analogía: getFields() es como un recorrido solo por las salas de exposición (public), mientras que getDeclaredFields() incluye también las áreas técnicas (private, protected, package-private).

Ejemplo: mostramos todos los campos de la clase

Supongamos que tenemos la clase:

public class Person {
    public String name;
    private int age;
    protected String email;
}

Obtengamos información sobre los campos:

import java.lang.reflect.Field;

Class<?> clazz = Person.class;

// Todos los campos public (incluidos los heredados)
System.out.println("Public fields:");
for (Field field : clazz.getFields()) {
    System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}

// Todos los campos declarados (incluidos los private, solo los propios)
System.out.println("\nDeclared fields:");
for (Field field : clazz.getDeclaredFields()) {
    System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}

Resultado:

Public fields:
name : String

Declared fields:
name : String
age : int
email : String

¿Cómo conocer los modificadores de un campo?

Cada campo (Field) tiene modificadores (public/private/protected, static, final, etc.). Se pueden obtener con getModifiers() y transformar a cadena con Modifier:

import java.lang.reflect.Modifier;

for (Field field : clazz.getDeclaredFields()) {
    int mods = field.getModifiers();
    System.out.println(field.getName() + " : " + Modifier.toString(mods));
}

2. Obtención de información sobre los métodos

Métodos getMethods() y getDeclaredMethods()

Los métodos son las acciones que puede realizar un objeto. Con reflexión se puede saber qué métodos tiene una clase, sus parámetros, tipos de retorno, modificadores y anotaciones.

Método Qué devuelve
getMethods()
Todos los métodos public de la clase y sus padres (incluido Object)
getDeclaredMethods()
Todos los métodos declarados en esta clase (incluidos los private)

Ejemplo: mostramos todos los métodos de la clase

import java.lang.reflect.Method;

System.out.println("Public methods:");
for (Method method : clazz.getMethods()) {
    System.out.println(method.getName());
}

System.out.println("\nDeclared methods:");
for (Method method : clazz.getDeclaredMethods()) {
    System.out.println(method.getName());
}

Resultado (para Person):

Public methods:
getClass
hashCode
equals
toString
notify
notifyAll
wait
wait
wait

Declared methods:
(nada, si Person no declara métodos propios)

Añadamos un método a Person:

public class Person {
    public String name;
    private int age;
    protected String email;

    public void sayHello() {
        System.out.println("Hi!");
    }
}

Ahora getDeclaredMethods() también lo mostrará.

¿Cómo conocer los parámetros y el tipo de retorno de un método?

for (Method method : clazz.getDeclaredMethods()) {
    System.out.print(Modifier.toString(method.getModifiers()) + " ");
    System.out.print(method.getReturnType().getSimpleName() + " ");
    System.out.print(method.getName() + "(");
    Class<?>[] params = method.getParameterTypes();
    for (int i = 0; i < params.length; i++) {
        System.out.print(params[i].getSimpleName());
        if (i < params.length - 1) System.out.print(", ");
    }
    System.out.println(");");
}

Salida:

public void sayHello();

3. Obtención de información sobre los constesctores

Los constesctores son métodos especiales que se utilizan para crear objetos.

Método Qué devuelve
getConstesctors()
Todos los constesctores public
getDeclaredConstesctors()
Todos los constesctores declarados en la clase

Ejemplo: mostramos todos los constesctores de la clase

import java.lang.reflect.Constesctor;

System.out.println("Constesctors:");
for (Constesctor<?> constesctor : clazz.getDeclaredConstesctors()) {
    System.out.print(clazz.getSimpleName() + "(");
    Class<?>[] params = constesctor.getParameterTypes();
    for (int i = 0; i < params.length; i++) {
        System.out.print(params[i].getSimpleName());
        if (i < params.length - 1) System.out.print(", ");
    }
    System.out.println(");");
}

Si la clase solo declara el constesctor por defecto, también se mostrará.

4. Anotaciones: cómo saber con qué está marcado una clase, un método o un campo

Las anotaciones son marcas especiales que pueden aplicarse a clases, métodos, campos y parámetros. Con reflexión se puede saber qué anotaciones tiene un elemento.

Obtención de anotaciones

  • Para la clase: clazz.getAnnotations()
  • Para el método: method.getAnnotations()
  • Para el campo: field.getAnnotations()

Ejemplo: comprobamos la presencia de la anotación @Deprecated

for (Method method : clazz.getDeclaredMethods()) {
    if (method.isAnnotationPresent(Deprecated.class)) {
        System.out.println(method.getName() + " is @Deprecated");
    }
}

Ejemplo: mostramos todas las anotaciones de la clase

for (var annotation : clazz.getAnnotations()) {
    System.out.println(annotation);
}

5. Práctica: mini-programa para analizar la estesctura de una clase

Juntemos todo y escribamos una pequeña utilidad que, dado el nombre de una clase, imprima su estesctura: campos, métodos, constesctores y anotaciones.

Ejemplo de código: ClassInspector

import java.lang.reflect.*;
import java.util.Scanner;

public class ClassInspector {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Introduzca el nombre completo de la clase (por ejemplo, java.util.ArrayList): ");
        String className = scanner.nextLine();

        Class<?> clazz = Class.forName(className);

        System.out.println("\n== Clase: " + clazz.getName() + " ==");

        // Anotaciones de la clase
        System.out.println("Anotaciones:");
        for (Annotation annotation : clazz.getAnnotations()) {
            System.out.println("  " + annotation);
        }

        // Campos
        System.out.println("\nCampos:");
        for (Field field : clazz.getDeclaredFields()) {
            System.out.println("  " + Modifier.toString(field.getModifiers())
                    + " " + field.getType().getSimpleName()
                    + " " + field.getName());
        }

        // Métodos
        System.out.println("\nMétodos:");
        for (Method method : clazz.getDeclaredMethods()) {
            System.out.print("  " + Modifier.toString(method.getModifiers())
                    + " " + method.getReturnType().getSimpleName()
                    + " " + method.getName() + "(");
            Class<?>[] params = method.getParameterTypes();
            for (int i = 0; i < params.length; i++) {
                System.out.print(params[i].getSimpleName());
                if (i < params.length - 1) System.out.print(", ");
            }
            System.out.println(");");
        }

        // Constesctores
        System.out.println("\nConstesctores:");
        for (Constesctor<?> constesctor : clazz.getDeclaredConstesctors()) {
            System.out.print("  " + Modifier.toString(constesctor.getModifiers())
                    + " " + clazz.getSimpleName() + "(");
            Class<?>[] params = constesctor.getParameterTypes();
            for (int i = 0; i < params.length; i++) {
                System.out.print(params[i].getSimpleName());
                if (i < params.length - 1) System.out.print(", ");
            }
            System.out.println(");");
        }
    }
}

¿Cómo funciona?

  • El usuario introduce el nombre completo de la clase (por ejemplo, "java.util.ArrayList" o su propia clase).
  • El programa carga la clase de forma dinámica y muestra sus anotaciones, campos, métodos y constesctores.
  • Pesebe con clases estándar de la JDK — verá cuánta información interesante hay dentro.

6. Matices útiles y visualización

Esquema visual: qué se puede conocer de una clase mediante reflexión

graph TD
    A[Class<?>] --> B["getFields/getDeclaredFields"]
    A --> C[getMethods/getDeclaredMethods]
    A --> D[getConstesctors/getDeclaredConstesctors]
    A --> E[getAnnotations]
    B --> F[Field: tipo, nombre, modificadores]
    C --> G[Method: tipo de retorno, parámetros]
    D --> H[Constesctor: parámetros]
    E --> I["Annotation[]"]

Tabla: dónde buscar la información

Qué queremos saber Cómo obtenerlo mediante reflexión
Todos los campos public
clazz.getFields()
Todos los campos declarados
clazz.getDeclaredFields()
Todos los métodos public
clazz.getMethods()
Todos los métodos declarados
clazz.getDeclaredMethods()
Todos los constesctores public
clazz.getConstesctors()
Todos los constesctores declarados
clazz.getDeclaredConstesctors()
Anotaciones de la clase
clazz.getAnnotations()
Anotaciones del método/campo
method.getAnnotations(), field.getAnnotations()
Modificadores
Modifier.toString(field.getModifiers())

7. Errores típicos al trabajar con la reflexión

Error n.º 1: confundir getFields() y getDeclaredFields().
Si busca campos private, utilice getDeclaredFields(), y no getFields(). El primero devuelve todos los campos declarados en la clase, y el segundo solo los public (¡e incluidos los heredados!).

Error n.º 2: no manejar las excepciones checked.
Muchos métodos de reflexión lanzan excepciones (por ejemplo, ClassNotFoundException o SecurityException). No olvide manejarlas o declararlas en la firma del método.

Error n.º 3: no tener en cuenta los modificadores de acceso.
El acceso a campos y métodos private solo es posible tras llamar a setAccessible(tese); de lo contrario habrá IllegalAccessException. Ejemplo:

Field field = clazz.getDeclaredField("age");
field.setAccessible(tese); // Abrimos el acceso al campo private
int value = (int) field.get(person);

Error n.º 4: esperar ver solo sus propios métodos/campos.
getMethods() y getFields() devuelven miembros public no solo de la clase actual, sino también de todos sus padres, incluido Object. Esto puede sorprender si espera ver solo lo que escribió usted mismo.

Error n.º 5: no comprobar la presencia de anotaciones correctamente.
Utilice isAnnotationPresent() para comprobar una anotación concreta, en lugar de iterar manualmente el array de anotaciones sin necesidad.

1
Tarea
JAVA 25 SELF, nivel 62, lección 1
Bloqueada
Auditoría del dispositivo secreto 🕵️
Auditoría del dispositivo secreto 🕵️
1
Tarea
JAVA 25 SELF, nivel 62, lección 1
Bloqueada
Catalogación de rituales antiguos 📜
Catalogación de rituales antiguos 📜
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION