Reflexión Java: ¿Cómo obtener el nombre de una variable?

Resuelto David Koelle asked hace 15 años • 8 respuestas

Usando Java Reflection, ¿es posible obtener el nombre de una variable local? Por ejemplo, si tengo esto:

Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();

¿Es posible implementar un método que pueda encontrar los nombres de esas variables, así:

public void baz(Foo... foos)
{
    for (Foo foo: foos) {
        // Print the name of each foo - b, a, and r
        System.out.println(***); 
    }
}

EDITAR: Esta pregunta es diferente de ¿Existe alguna forma en Java de encontrar el nombre de la variable que se pasó a una función? en el sentido de que plantea de manera más pura la pregunta sobre si se puede usar la reflexión para determinar el nombre de una variable local, mientras que la otra pregunta (incluida la respuesta aceptada) se centra más en probar los valores de las variables.

David Koelle avatar Apr 13 '09 22:04 David Koelle
Aceptado

A partir de Java 8, cierta información del nombre de la variable local está disponible mediante reflexión. Consulte la sección "Actualización" a continuación.

La información completa suele almacenarse en archivos de clase. Una optimización en tiempo de compilación es eliminarlo, ahorrando espacio (y proporcionando cierta confusión). Sin embargo, cuando está presente, cada método tiene un atributo de tabla de variables locales que enumera el tipo y nombre de las variables locales, y el rango de instrucciones en las que se encuentran dentro del alcance.

Quizás una biblioteca de ingeniería de código de bytes como ASM le permitiría inspeccionar esta información en tiempo de ejecución. El único lugar razonable que se me ocurre para necesitar esta información es en una herramienta de desarrollo, por lo que la ingeniería de código de bytes probablemente también sea útil para otros fines.


Actualización: se agregó soporte limitado para esto a Java 8. Los nombres de los parámetros (una clase especial de variable local) ahora están disponibles mediante reflexión. Entre otros propósitos, esto puede ayudar a reemplazar @ParameterNamelas anotaciones utilizadas por los contenedores de inyección de dependencia.

erickson avatar Apr 13 '2009 15:04 erickson

No es posible en absoluto. Los nombres de las variables no se comunican dentro de Java (y también pueden eliminarse debido a optimizaciones del compilador).

EDITAR (relacionado con comentarios):

Si se aleja de la idea de tener que usarlo como parámetro de función, aquí tiene una alternativa (que yo no usaría; consulte a continuación):

public void printFieldNames(Object obj, Foo... foos) {
    List<Foo> fooList = Arrays.asList(foos);
    for(Field field : obj.getClass().getFields()) {
         if(fooList.contains(field.get()) {
              System.out.println(field.getName());
         }
    }
}

Habrá problemas si a == b, a == r, or b == rhay otros campos que tengan las mismas referencias.

EDITAR ahora es innecesario ya que se aclaró la pregunta

Marcel Jackwerth avatar Apr 13 '2009 15:04 Marcel Jackwerth