En utilisant Java Reflection, est-il possible d'obtenir le nom d'une variable locale? Par exemple, si j'ai ceci:
Foo b = new Foo();
Foo a = new Foo();
Foo r = new Foo();
est-il possible d'implémenter une méthode qui peut trouver les noms de ces variables, comme ceci:
public void baz(Foo... foos)
{
for (Foo foo: foos) {
// Print the name of each foo - b, a, and r
System.out.println(***);
}
}
EDIT: Cette question est différente de Y a-t-il un moyen en Java de trouver le nom de la variable qui a été passée à une fonction? en ce qu 'elle pose plus purement la question de savoir si l'on peut utiliser la réflexion pour déterminer le nom d'une variable locale, alors que l'autre question (y compris la réponse acceptée) est plus centrée sur le test des valeurs de variables.
java
reflection
David Koelle
la source
la source
Réponses:
À partir de Java 8, certaines informations de nom de variable locale sont disponibles par réflexion. Consultez la section «Mise à jour» ci-dessous.
Des informations complètes sont souvent stockées dans des fichiers de classe. Une optimisation au moment de la compilation consiste à le supprimer, en économisant de l'espace (et en fournissant une certaine obsfuscation). Cependant, lorsqu'elle est présente, chaque méthode a un attribut de table de variables locales qui répertorie le type et le nom des variables locales, ainsi que la plage d'instructions où elles sont dans la portée.
Peut-être une bibliothèque d'ingénierie de code d'octet comme ASM vous permettrait d'inspecter ces informations au moment de l'exécution. Le seul endroit raisonnable auquel je puisse penser pour avoir besoin de ces informations est dans un outil de développement, et donc l'ingénierie de byte-code est susceptible d'être utile à d'autres fins également.
Mise à jour: une prise en charge limitée a été ajoutée à Java 8. Les noms de paramètres (une classe spéciale de variables locales) sont désormais disponibles via la réflexion. Entre autres objectifs, cela peut aider à remplacer les
@ParameterName
annotations utilisées par les conteneurs d'injection de dépendances.la source
Ce n'est pas possible. Les noms de variables ne sont pas communiqués dans Java (et peuvent également être supprimés en raison des optimisations du compilateur).
EDIT (lié aux commentaires):
Si vous vous éloignez de l'idée de devoir l'utiliser comme paramètres de fonction, voici une alternative (que je n'utiliserais pas - voir ci-dessous):
Il y aura des problèmes si
a == b, a == r, or b == r
ou il y a d'autres champs qui ont les mêmes références.EDIT maintenant inutile puisque la question a été clarifiée
la source
( Modifier: deux réponses précédentes supprimées, une pour répondre à la question telle qu'elle se présentait avant les modifications et une pour être, si ce n'est absolument faux, du moins proche. )
Si vous compilez avec les informations de débogage sur (
javac -g
), les noms des variables locales sont conservés dans le fichier .class. Par exemple, prenez cette classe simple:Après la compilation avec
javac -g:vars TestLocalVarNames.java
, les noms des variables locales sont maintenant dans le fichier .class.javap
de-l
indicateur de ("Imprimer le numéro de ligne et les tables de variables locales") peut les afficher.javap -l -c TestLocalVarNames
spectacles:La spécification VM explique ce que nous voyons ici:
§4.7.9 L'
LocalVariableTable
attribut :le
LocalVariableTable
stocke les noms et les types des variables dans chaque emplacement, il est donc possible de les faire correspondre avec le bytecode. C'est ainsi que les débogueurs peuvent faire "Evaluate expression".Comme l'a dit Erickson, cependant, il n'y a aucun moyen d'accéder à cette table par une réflexion normale. Si vous êtes toujours déterminé à le faire, je pense que l' architecture du débogueur de plate-forme Java (JPDA) vous aidera (mais je ne l'ai jamais utilisée moi-même).
la source
javac
place une table de variables locales dans la classe pour chaque méthode pour faciliter le débogage. Utilisez l'-l
option pourjavap
afficher la table des variables locales.javac -g:vars
pour l'obtenir. (J'essaie de modifier cette réponse depuis trois heures, mais comme je l'ai dit, ma connexion réseau rencontre des problèmes, ce qui rend la recherche difficile.)la source
getDeclaredFields()
peut être utilisé au cas où vous voudriez également des noms de champs privésVous pouvez faire comme ceci:
la source
Tout ce que vous avez à faire est de créer un tableau de champs, puis de le définir dans la classe souhaitée, comme indiqué ci-dessous.
Par exemple si vous avez fait
tu aurais
la source
mettre à jour la réponse de @Marcel Jackwerth pour le général.
et ne travaillant qu'avec l'attribut de classe, ne fonctionnant pas avec la variable de méthode.
la source
voir cet exemple:
la source