L’utilisation de Java réflexion, est-il possible d’obtenir le nom d’une variable locale ? Par exemple, si j’ai ceci :
est-il possible d’implémenter une méthode qui peut trouver les noms de ces variables, comme suit :
L’utilisation de Java réflexion, est-il possible d’obtenir le nom d’une variable locale ? Par exemple, si j’ai ceci :
est-il possible d’implémenter une méthode qui peut trouver les noms de ces variables, comme suit :
Comme de Java 8, certains nom de variable locale d'information est disponible par le biais de la réflexion. Voir la "mise à Jour" section ci-dessous.
Des informations complètes sont souvent stockées dans des fichiers de classe. Une compilation d'optimisation est de les enlever, un gain d'espace (et de la fourniture de certains obsfuscation). Toutefois, lorsqu'il est présent, chaque méthode a une variable locale de la table d'attribut qui indique le type et le nom des variables locales, et la gamme des instructions où ils sont à portée.
Peut-être un byte-code de l'ingénierie de la bibliothèque, comme l'ASM devrait vous permettre de consulter ces renseignements au moment de l'exécution. La seule raisonnable je pense, ont besoin de cette information est un outil de développement, et ainsi de byte-code de l'ingénierie sont susceptibles d'être utiles à d'autres fins aussi.
Mise à jour: prise en charge Limitée pour cet été ajoutée à Java 8. Paramètre (une classe spéciale de la variable locale), les noms sont maintenant disponibles par l'intermédiaire de la réflexion. Parmi d'autres fins, ce qui peut aider à remplacer @ParameterName
annotations utilisées par l'injection de dépendance des conteneurs.
C'est pas du tout possible. Les noms de variables ne sont pas communiquées dans un délai de Java (et peut également être retiré en raison d'optimisations du compilateur).
EDIT (liées aux commentaires):
Si vous prenez du recul à partir de l'idée d'avoir à l'utiliser comme paramètres de la fonction, voici une autre (que je ne voudrais pas l'utiliser, voir ci - dessous):
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());
}
}
}
Il y aura des problèmes si a == b, a == r, or b == r
ou il y a d'autres domaines qui ont les mêmes références.
EDIT désormais inutile puisque la question a obtenu précisé
(Edit: deux réponses précédentes supprimés, un pour répondre à la question telle qu'elle était avant les modifications et de les un pour être, si pas tout à fait tort, au moins près de lui.)
Si vous compilez avec les informations de débogage (javac -g
), les noms de variables locales sont conservés dans le .fichier de classe. Par exemple, prenez cette classe simple:
class TestLocalVarNames {
public String aMethod(int arg) {
String local1 = "a string";
StringBuilder local2 = new StringBuilder();
return local2.append(local1).append(arg).toString();
}
}
Après la compilation avec javac -g:vars TestLocalVarNames.java
, les noms de variables locales sont maintenant dans la .fichier de classe. javap
s' -l
drapeau ("Imprimer le numéro de ligne et local des tableaux de variables") de les montrer.
javap -l -c TestLocalVarNames
montre:
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 VM spec explique ce que nous voyons ici:
§4.7.9 L' LocalVariableTable
D'Attribut:
L'
LocalVariableTable
attribut est facultative et la longueur de la variable attribut d'unCode
(§4.7.3) attribut. Il peut être utilisé par les débogueurs pour déterminer la valeur d'une variable locale au cours de l'exécution d'une méthode.
L' LocalVariableTable
stocke les noms et les types des variables dans chaque fente, de sorte qu'il est possible de les faire correspondre avec le bytecode. C'est de cette façon débogueurs peut le faire "Évaluer l'expression".
Comme erickson a dit, cependant, il n'y a aucun moyen d'accéder à cette table en cours de réflexion. Si vous êtes toujours décidé à le faire, je crois que la Plate-forme Java Débogueur Architecture (JPDA) aidera (mais je n'ai jamais utilisé moi-même).
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));
}
}
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.