Comment obtenir le source de nom de fichier/ligne-numéro à partir d'un java.lang.Class objet
Est-il possible, compte tenu d'une java.lang.Class
objet, pour obtenir le nom du fichier source et le numéro de la ligne à laquelle le recours a été déclaré?
Les données devraient être disponibles dans les .class
du fichier d'informations de débogage. Le seul endroit que je connais, où le JDK retourne les informations de débogage est dans java.lang.StackTraceElement
mais je ne suis pas sûr si c'est possible à force de Java pour créer un java.lang.StackTraceElement
exemple pour un usage arbitraire de la classe, parce que nous ne sommes pas à l'exécution d'une méthode dans la classe.
Mon exact de cas d'utilisation est un anonyme intérieur de la classe qui a un générés par le compilateur nom. Je veux savoir le nom de fichier et le numéro de ligne de la déclaration de classe.
Je préfère ne pas utiliser un byte-code de la manipulation, mais je peux retomber si je dois le faire.
Lorsque vous déboguez une application et que vous voyez un objet d'une classe générique à partir de laquelle vous avez plusieurs instances. Mais tous ces cas, une référence à un
Listener
instance où Listener
est une interface ou une classe abstraite. Vous pouvez les distinguer par le béton de classe de leur Listener
référence: si c'est un XxxListener
vous lire XxxListener.java
et obtenir une idée de ce qu'est-ce qu'il va faire, mais que pouvez-vous faire si le Listener
est une instance de SomeOuterClass$12
?vous avez juste fait de l'argument pour expliquer pourquoi vous devriez définir l'ensemble de vos auditeurs nommés des classes. Il va ajouter ligne de code supplémentaire, mais de simplifier le débogage, rendre les méthodes où vous créez votre interface des objets beaucoup plus lisible, et de faire vos modules plus facile à maintenir, dans l'ensemble.
Vous êtes argument implique réellement interdisant anonyme classes tout à fait, parce qu'ils ne seront pas obtenir un nom significatif de toute façon et de débogage sans nom est difficile. Je ne suis pas avec cet argument. Anonyme les classes internes sont utiles pour le langage et ils vont devenir encore plus courantes pour le lambda de la syntaxe de sucre est ajoutée à Java. Je crois donc que nous devons trouver un moyen d'activer le débogage plutôt que l'inverse.
mon argument n'implique pas l'interdisant les classes internes anonymes, simplement en limitant leur utilisation. Pour de courte durée ou à portée limitée des opérations, je n'ai pas de questions. Quelque chose qui est de longue durée, ou de l'étendue du mérite son propre nom.
OriginalL'auteur Saintali | 2011-09-20
Vous devez vous connecter pour publier un commentaire.
La réponse à ce qui revient à combien vous avez de contrôle sur le code qui est la mise en œuvre de l'Auditeur. Vous avez raison, il n'est pas possible de créer une stacktrace sans être dans une méthode.
La technique générale est de créer une Exception(), dans le constructeur, mais de ne pas le jeter. Il contient la stacktrace de l'information, que vous pouvez utiliser comme vous le souhaitez. Cela vous donnera le numéro de la ligne du constructeur, mais pas de la classe. Veuillez noter que cette méthode n'est pas particulièrement performant, car la création d'une stacktrace est cher.
Vous devrez soit:
Pour 1), il vous suffit de mettre à l'Exception de la création dans la classe abstraite, et le constructeur est appelé par le sous-classe:
ce qui produit quelque chose comme:
En général, il ya quelques règles de nommage qui sont suivies: Si vous avez un extérieur de la classe appelée Acteur et un intérieur appelé à la Consommation, puis la classe compilée sera appelé Acteur$Consommateur. Anonyme les classes internes sont nommés dans l'ordre dans lequel elles apparaissent dans le fichier, de sorte que l'Acteur$1 apparaîtra dans le fichier avant de le Acteur de$2. Je ne pense pas que cela est spécifié nulle part, donc c'est probablement juste une convention, et ne doit pas être invoqué si vous faites quelque chose de sophistiqué avec plusieurs machines virtuelles etc.
Il est possible, comme jmg a souligné, que vous pouvez définir plusieurs haut niveau de classes dans le même fichier. Si vous avez un public class Toto, ce doit être défini dans Foo.java, mais d'un non-publique de la classe peuvent être inclus dans un autre fichier. La méthode ci-dessus va faire face à ce.
Explication:
Si vous démontez la java (javap -c -verbose), vous verrez qu'il y a des numéros de ligne dans les informations de débogage, mais ils s'appliquent uniquement aux méthodes. En utilisant les éléments suivants intérieure:
et la javap sortie contient:
La LineNumberTable contient la liste des numéros de ligne qui s'appliquent à une méthode. Donc, mon constructeur pour le Consommateur commence à la ligne 20. Mais c'est la première ligne du constructeur, pas la première ligne de la classe. Il n'est que la même ligne, parce que je suis en utilisant le constructeur par défaut. Si j'ajoute un constructeur, le numéro de ligne va changer. le compilateur ne pas stocker la ligne que la classe est déclarée. Donc vous ne pouvez pas trouver où la classe est déclarée sans l'analyse de la java lui-même. Vous simplement ne pas avoir les informations disponibles.
Toutefois, si vous utilisez un anonyme intérieur de la classe, tels que:
Puis le numéro de la ligne du constructeur et la classe va correspondre à[*], de sorte que cela vous donne un numéro de ligne.
[*] Sauf si le "nouveau" et "Runnable()" sont sur des lignes différentes.
getDeclaredConstructors
(comment pourrait-il en avoir plus, ou moins?) et le numéro de la ligne du constructeur de la classe anonyme lui-même. pouvez-vous vous intégrer dans votre réponse?Oui, vous avez raison. Mise à jour de vos informations.
Pas besoin de créer une exception, l'utilisation
Thread.currentThread().getStackTrace()
.OriginalL'auteur Matthew Farwell
Vous pouvez trouver de l'uet ligne de code:
Mais il semble que
StackTraceElements
sont créés par des natifs JDK méthode à l'intérieur d'Throwable
.Événement si vous utilisez byte-code de la manipulation cadre, pour ajouter une méthode à une classe qui crée throwable, vous n'obtiendrez pas la bonne ligne de code de déclaration de classe.
OriginalL'auteur Piotr Gwiazda
Vous pouvez obtenir une trace de pile d'un thread en appelant getStackTrace(). Donc pour le thread en cours, vous devez appeler
Thread.currentThread().getStackTrace()
.OriginalL'auteur Robert
À vos fins, en générant une exception juste pour ses trace de la pile est la bonne réponse.
Mais dans les cas où cela ne fonctionne pas, vous pouvez également utiliser Apache BCEL pour analyser Java byte code. Si cela sonne comme lourde overkill, vous avez probablement raison.
(Avertissement: je n'ai pas testé ce code.)
Une autre option est de construire une coutume doclet pour recueillir les métadonnées appropriées au moment de la compilation. J'ai utilisé dans le passé pour une application qui a besoin de savoir, au moment de l'exécution de toutes les sous-classes d'une classe mère. En les ajoutant à une méthode de fabrique était trop lourd, et cela m'a fait directement le lien de javadoc.
Maintenant que je suis en train d'écrire un nouveau code de la Scala, je suis en train d'étudier à l'aide d'une technique comme ci-dessus, et de générer une liste de classes par une recherche dans le répertoire de construction.
OriginalL'auteur David Leppik
C'est la façon dont je l'ai fait:
EDIT: en Regardant en arrière sur ce, je serais probablement utiliser des AOP pour le faire maintenant. En fait, certaines modifications mineures à ce projet et je pourrais probablement le faire. Voici une pile question avec un soupçon.
OriginalL'auteur djangofan
Le fichier source est dans la plupart des cas fortement lié au nom de la classe. Il n'y a qu'une seule ligne dans le fichier dans lequel la classe est déclarée. Il n'est pas nécessaire pour ce genre d'informations sans ambiguïté à être codé dans les informations de débogage.
Pourquoi?
Il n'est pas commun mais très bien possible d'avoir plusieurs de premier niveau classes dans un code source Java fichier. Il y a ensuite aucun corrélation entre la source et le nom de fichier --- seulement à son chemin d'accès au fichier.
OriginalL'auteur user207421
Cette réponse ne couvre pas les numéros de ligne, mais répond à mes besoins et de travailler pour n'importe quel fichier source que vous possédez.
C'est une réponse pour trouver l'emplacement d'un fichier source basé sur un fichier de classe pour une IDE qui a de multiples projets. Elle s'appuie sur le chargeur de classe et de votre projet java conventions pour résoudre ce problème.
Vous devrez mettre à jour votre dossier source (src) et le dossier de sortie (bin) pour correspondre à votre convention. Vous devrez fournir votre propre mise en œuvre de
Voici le code
OriginalL'auteur englebart