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?
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 ¿Hay alguna forma en Java de encontrar el nombre de la variable que se pasó a una función? en el sentido de que hace una pregunta más pura sobre si uno 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.
java
reflection
David Koelle
fuente
fuente
Respuestas:
A partir de Java 8, parte de la información del nombre de la variable local está disponible a través de la reflexión. Consulte la sección "Actualización" a continuación.
La información completa a menudo se almacena en archivos de clase. Una optimización en tiempo de compilación es eliminarlo, ahorrando espacio (y proporcionando algo de ofuscación). Sin embargo, cuando está presente, cada método tiene un atributo de tabla de variables locales que enumera el tipo y el nombre de las variables locales, y el rango de instrucciones donde están 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 en el que puedo pensar para necesitar esta información es en una herramienta de desarrollo, por lo que es probable que la ingeniería de código de bytes también sea útil para otros fines.
Actualización: se agregó soporte limitado para esto a Java 8. Los nombres de parámetros (una clase especial de variable local) ahora están disponibles a través de la reflexión. Entre otros propósitos, esto puede ayudar a reemplazar las
@ParameterName
anotaciones utilizadas por los contenedores de inyección de dependencia.fuente
Es que no es posible en absoluto. Los nombres de las variables no se comunican dentro de Java (y también pueden eliminarse debido a las optimizaciones del compilador).
EDITAR (relacionado con comentarios):
Si abandonas la idea de tener que usarlo como parámetros de función, aquí hay una alternativa (que no usaría, ver más abajo):
Habrá problemas si
a == b, a == r, or b == r
hay otros campos que tengan las mismas referencias.EDITAR ahora innecesario ya que la pregunta se aclaró
fuente
( Editar: se eliminaron dos respuestas anteriores, una por responder la pregunta tal como estaba antes de las ediciones y otra por estar, si no está absolutamente equivocada, al menos cerca de ella. )
Si compila con información de depuración en (
javac -g
), los nombres de las variables locales se mantienen en el archivo .class. Por ejemplo, tome esta clase simple:Después de compilar con
javac -g:vars TestLocalVarNames.java
, los nombres de las variables locales ahora están en el archivo .class.javap
El-l
indicador ("Imprimir número de línea y tablas de variables locales") puede mostrarlas.javap -l -c TestLocalVarNames
muestra:La especificación de VM explica lo que estamos viendo aquí:
§4.7.9 El
LocalVariableTable
atributo :Las
LocalVariableTable
tiendas de los nombres y tipos de las variables en cada ranura, por lo que es posible igualar para arriba con el código de bytes. Así es como los depuradores pueden hacer "Evaluar expresión".Sin embargo, como dijo Erickson, no hay forma de acceder a esta tabla a través de la reflexión normal. Si todavía está decidido a hacer esto, creo que la arquitectura Java Platform Debugger Architecture (JPDA) ayudará (pero nunca la he usado yo mismo).
fuente
javac
coloca una tabla de variables locales en la clase para cada método para ayudar a la depuración. Use la-l
opción parajavap
ver la tabla de variables locales.javac -g:vars
para conseguirlo. (He estado tratando de editar esta respuesta durante las últimas tres horas, pero como dije, mi conexión de red tiene problemas, lo que dificulta la investigación)fuente
getDeclaredFields()
puede usarse en caso de que también desee los nombres de los campos privadosPuedes hacer así:
fuente
Todo lo que necesita hacer es hacer una matriz de campos y luego configurarlo en la clase que desee como se muestra a continuación.
Por ejemplo si lo hiciste
obtendrías
fuente
actualizar la respuesta de @Marcel Jackwerth para general.
y solo funciona con el atributo de clase, no funciona con la variable de método.
fuente
mira este ejemplo:
fuente