variable una que obtener objeto nombre name imagen example java reflection

una - obtener nombre de imagen java



Reflexión de Java: ¿cómo obtener el nombre de una variable? (7)

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 ¿Hay alguna forma en Java para encontrar el nombre de la variable que se pasó a una función? en que pregunta de manera más pura si se puede utilizar 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.


( Editar: se eliminaron dos respuestas anteriores, una para responder a la pregunta tal como estaba antes de las ediciones y una para ser, si no absolutamente incorrecta, al menos cercana a 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, toma esta clase simple:

class TestLocalVarNames { public String aMethod(int arg) { String local1 = "a string"; StringBuilder local2 = new StringBuilder(); return local2.append(local1).append(arg).toString(); } }

Después de compilar con javac -g:vars TestLocalVarNames.java , los nombres de las variables locales ahora están en el archivo .class. El indicador javap ''s -l ("Número de línea de impresión y tablas de variables locales") puede mostrarlos.

javap -l -c TestLocalVarNames muestra:

class TestLocalVarNames extends java.lang.Object{ TestLocalVarNames(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LTestLocalVarNames; public java.lang.String aMethod(int); Code: 0: ldc #2; //String a string 2: astore_2 3: new #3; //class java/lang/StringBuilder 6: dup 7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 10: astore_3 11: aload_3 12: aload_2 13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: iload_1 17: invokevirtual #6; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 20: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 23: areturn LocalVariableTable: Start Length Slot Name Signature 0 24 0 this LTestLocalVarNames; 0 24 1 arg I 3 21 2 local1 Ljava/lang/String; 11 13 3 local2 Ljava/lang/StringBuilder; }

La especificación de VM explica lo que estamos viendo aquí:

§4.7.9 El atributo LocalVariableTable :

El atributo LocalVariableTable es un atributo opcional de longitud variable de un atributo de Code (§4.7.3). Puede ser utilizado por los depuradores para determinar el valor de una variable local dada durante la ejecución de un método.

LocalVariableTable almacena los nombres y tipos de las variables en cada ranura, por lo que es posible hacer coincidirlos con el bytecode. Así es como los depuradores pueden hacer "Evaluar expresión".

Sin embargo, como dijo Erickson, no hay forma de acceder a esta mesa a través de la reflexión normal. Si todavía está decidido a hacer esto, creo que la Java Platform Debugger Architecture (JPDA) ayudará (pero nunca la he usado).


A partir de Java 8, parte de la información del nombre de variable local está disponible a través de la reflexión. Vea la sección "Actualizar" 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 cierta obstrucción). Sin embargo, cuando está presente, cada método tiene un atributo de tabla variable local que enumera el tipo y el nombre de las variables locales, y el rango de instrucciones en el que están dentro del alcance.

Quizás una biblioteca de ingeniería de código de bytes como ASM le permita 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 la ingeniería de código byte también puede ser ú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 fines, esto puede ayudar a reemplazar @ParameterName anotaciones @ParameterName utilizadas por los contenedores de inyección de dependencias.


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 los comentarios):

Si se aleja de la idea de tener que usarlo como parámetros de función, aquí hay una alternativa (que no usaría - vea abajo):

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 == r o hay otros campos que tienen las mismas referencias.

EDITAR ahora innecesario ya que la pregunta fue aclarada


Puedes hacer así:

Field[] fields = YourClass.class.getDeclaredFields(); //gives no of fields System.out.println(fields.length); for (Field field : fields) { //gives the names of the fields System.out.println(field.getName()); }


Todo lo que necesita hacer es crear una matriz de campos y luego configurarla en la clase que desee, como se muestra a continuación.

Field fld[] = (class name).class.getDeclaredFields(); for(Field x : fld) {System.out.println(x);}

Por ejemplo, si lo hiciste

Field fld[] = Integer.class.getDeclaredFields(); for(Field x : fld) {System.out.println(x);}

obtendrías

public static final int java.lang.Integer.MIN_VALUE public static final int java.lang.Integer.MAX_VALUE public static final java.lang.Class java.lang.Integer.TYPE static final char[] java.lang.Integer.digits static final char[] java.lang.Integer.DigitTens static final char[] java.lang.Integer.DigitOnes static final int[] java.lang.Integer.sizeTable private static java.lang.String java.lang.Integer.integerCacheHighPropValue private final int java.lang.Integer.value public static final int java.lang.Integer.SIZE private static final long java.lang.Integer.serialVersionUID


mira este ejemplo:

PersonneTest pt=new PersonneTest(); System.out.println(pt.getClass().getDeclaredFields().length); Field[]x=pt.getClass().getDeclaredFields(); System.out.println(x[1].getName());


import java.lang.reflect.Field; public class test { public int i = 5; public Integer test = 5; public String omghi = "der"; public static String testStatic = "THIS IS STATIC"; public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException { test t = new test(); for(Field f : t.getClass().getFields()) { System.out.println(f.getGenericType() +" "+f.getName() + " = " + f.get(t)); } } }