Métodos de objetos de Java: getClass()

Este artículo es la continuación de una serie de artículos que describen los métodos a menudo olvidados de la clase de objeto base del lenguaje Java. A continuación se encuentran los met...

Introducción

Este artículo es una continuación de una serie de artículos que describen los métodos a menudo olvidados de la clase de objeto base del lenguaje Java. A continuación se muestran los métodos del Objeto Java básico presente en todos los objetos Java debido a la herencia implícita de Objeto junto con enlaces a cada artículo de esta serie.

El enfoque de este artículo es el método getClass(), que se utiliza para acceder a los metadatos sobre la clase del objeto con el que está trabajando.

El método getClass()

El método de objeto algo confuso o mal entendido getClass() devuelve una instancia de la clase Class, que contiene información sobre la clase desde la que se llamó a getClass(). Vaya, si no estás confundido por esa última declaración, ¡bien por ti, porque lo estoy y lo escribí!

Permítanme tratar de desempaquetar esa oración con una demostración de cómo podría usarse. A continuación encontrará la clase Person que utilicé en el artículo inicial sobre el método toString() de la clase Object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.adammcquistan.object;

import java.time.LocalDate;

public class Person {
    private String firstName;
    private String lastName;
    private LocalDate dob;

    public Person(String firstName, String lastName, LocalDate dob) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.dob = dob;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public LocalDate getDob() {
        return dob;
    }

    public void setDob(LocalDate dob) {
        this.dob = dob;
    }

    @Override
    public String toString() {
        return "<Person: firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
    }
}

Centrémonos en el método anulado toString(), que enumera el nombre de la clase, Persona, junto con los valores de los campos de la instancia. En lugar de "codificar" el nombre de la clase, Person, en la cadena en sí, podría haber usado el método getClass() para devolver una instancia de la clase Class, que contendrá esa información y me permitirá para usarlo así:

1
2
3
4
5
6
7
8
9
public class Person {
    // omitting everyting else remaining the same

    @Override
    public String toString() {
        Class c = getClass();
        return "<" + c.getName() + ": firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
    }
}

Esto llevaría a reemplazar el texto "Persona" codificado de forma rígida original con el nombre de clase completamente calificado de "com.adammcquistan.object.Person". La clase Class está repleta de diferentes métodos que le permiten identificar todo tipo de cosas sobre el objeto de clase al que se invocó getClass().

Por ejemplo, si quisiera obtener una representación toString() más simplificada de mi clase Persona, simplemente podría cambiar la llamada c.getName() con c.getSimpleName() como se muestra a continuación. Esto, a su vez, devolvería "Persona" en lugar del nombre de clase completo "com.adammcquistan.object.Person".

1
2
3
4
5
6
7
8
9
public class Person {
    // omitting everyting else remaining the same

    @Override
    public String toString() {
        Class c = getClass();
        return "<" + c.getSimpleName() + ": firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ">";
    }
}

Una gran diferencia en la semántica de cómo se usa getClass() en comparación con los otros métodos Object es que getClass() no se puede anular porque se declara como un método final.

¿Para qué sirve el objeto Clase? {#para quéesbuenoelobjetodeclase}

En este punto, es posible que se esté preguntando: "Ok, supongo que es genial que pueda obtener información sobre una clase llamando a getClass() y recuperando su representación de objeto Class, pero ¿cómo me resulta útil como programador?\ “. Créanme, yo también me he hecho esta pregunta y mi conclusión general ha sido que… no es así. Al menos no lo es realmente desde la perspectiva de un programador cotidiano. Sin embargo, si usted es un desarrollador de bibliotecas o marcos, es probable que se familiarice con la información y el comportamiento de los objetos Clase porque es esencial para el concepto conocido como [reflexión] (https://en.wikipedia .org/wiki/Reflection_(programación_computadora)).

La reflexión permite dos cosas principales: (i) la investigación en tiempo de ejecución de los objetos y sus contenidos y (ii) el acceso dinámico a los campos y la ejecución de métodos durante el tiempo de ejecución.

El elemento número uno ya se demostró anteriormente usando getClass() para obtener una representación en tiempo de ejecución de la clase Person para acceder al nombre de clase completo o simple en una versión modificada del método toString().

El segundo elemento es un poco más complicado para preparar un ejemplo, pero es algo que es bastante útil para poder acceder a los metadatos de una clase. Parte de la información para la que puede interrogar una instancia de Class son cosas como constructores, campos y métodos, además de otras cosas como jerarquías de herencia de una clase, como sus superclases e interfaces.

Un ejemplo de esto es la capacidad de usar depuradores en un IDE como Eclipse y Netbeans para ver los miembros y sus valores en una clase mientras el programa está en ejecución.

Tomemos por ejemplo lo siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class Main {
    public static void main(String[] args) {
        Person me = new Person("Adam", "McQuistan", LocalDate.parse("1987-09-23"));

        Class c = me.getClass();
        for (Field f : c.getDeclaredFields()) {
            f.setAccessible(true);
            try {
                System.out.println(f.getName() + " = " + f.get(me));
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
}

Daría como resultado lo siguiente:

1
2
3
firstName = Adam
lastName = McQuistan
dob = 1987-09-23

Nuevamente, ningún no masoquista probablemente haría esto en la programación diaria normal, pero verá que este tipo de cosas se hacen a menudo en los marcos.

Conclusión

En este artículo describí el significado y el uso del misterioso método getClass() de la clase Java Object. Mostré cómo se puede usar para obtener metadatos en una instancia de clase, como el nombre de la clase de un objeto en tiempo de ejecución, y brindé una explicación de por qué puede ser útil acceder a una instancia de clase.

Como siempre, gracias por leer y no se avergüence de comentar o criticar a continuación.

Licensed under CC BY-NC-SA 4.0