Comment obtenir le nom de la classe à partir d'une méthode statique dans cette classe. Par exemple
public class MyClass {
public static String getClassName() {
String name = ????; // what goes here so the string "MyClass" is returned
return name;
}
}
Pour le mettre en contexte, je veux en fait retourner le nom de classe dans le cadre d'un message dans une exception.
try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName();
}Réponses:
Afin de prendre en charge correctement le refactoring (renommer la classe), vous devez utiliser soit:
ou (merci à @James Van Huis ):
la source
Faites ce que dit la boîte à outils. Ne faites rien de tel:
la source
getClass
renvoie le type d'exécution, il ne peut donc pas être statique.Dans Java 7+, vous pouvez le faire dans des méthodes / champs statiques:
la source
Reflection.getCallerClass()
. Mais il donne un avertissement sur le fait d'être dans les packages «soleil». Cela pourrait donc être une meilleure solution.Reflection.getCallerClass()
chose non officielle . C'est un peu compliqué pour son opération triviale, c'est-à-direOptional<Class<?>> myself = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) .walk(s -> s.map(StackWalker.StackFrame::getDeclaringClass) .findFirst());
, mais bien sûr, cela est lié au fait qu'il sera beaucoup plus puissant.Donc, nous avons une situation où nous devons obtenir statiquement un objet de classe ou un nom complet / simple de classe sans utilisation explicite de la
MyClass.class
syntaxe.Il peut être très pratique dans certains cas, par exemple l'instance de l'enregistreur pour le kotlin fonctions de niveau supérieur (dans ce cas, kotlin crée une classe Java statique non accessible à partir du code kotlin).
Nous avons quelques variantes différentes pour obtenir ces informations:
new Object(){}.getClass().getEnclosingClass();
noté par Tom Hawtin - tackline
getClassContext()[0].getName();
de laSecurityManager
note de Christoffer
new Throwable().getStackTrace()[0].getClassName();
par le comte ludwig
Thread.currentThread().getStackTrace()[1].getClassName();
de Keksi
et enfin génial
MethodHandles.lookup().lookupClass();
de Rein
J'ai préparé un jmh les références pour toutes les variantes et tous les résultats sont:
Conclusions
Disponible uniquement depuis Java 7 et Android API 26!
Si vous en avez besoin dans de nombreux endroits et que vous ne voulez pas que votre bytecode gonfle en raison de tonnes de classes anonymes -
SecurityManager
c'est votre ami (troisième meilleure option).Mais vous ne pouvez pas simplement appeler
getClassContext()
- c'est protégé dans laSecurityManager
classe. Vous aurez besoin d'une classe d'aide comme celle-ci:getStackTrace()
exception from ou laThread.currentThread()
. Très inefficace et ne peut renvoyer que le nom de classe en tant que aString
, pas l'Class<*>
instance.PS
Si vous souhaitez créer une instance d'enregistreur pour les utilitaires de kotlin statiques (comme moi :), vous pouvez utiliser cet assistant:
Exemple d'utilisation:
la source
Cette instruction fonctionne bien:
la source
Thread.getStackTrace()
vous verrez qu'il ne fait rien d'autre quereturn (new Exception()).getStackTrace();
dans le cas d'être appelé sur lecurrentThread()
. La solution de @count ludwig est donc le moyen le plus direct d'y parvenir.Vous pouvez faire quelque chose de vraiment doux en utilisant JNI comme ceci:
MyObject.java:
puis:
puis:
MyObject.c:
Ensuite, compilez le C dans une bibliothèque partagée appelée
libclassname.so
et exécutez le java!*glousser
la source
Java_MyObject_getClassName
a le nom intégré. La solution consiste à utiliser le JNIRegisterNatives
. Bien sûr, il faudrait nourrir cela avec le JNIFindClass(env, 'com/example/MyObject')
, donc pas de victoire là-bas non plus.private static final String TAG = "MyClass"
ou l' autre: ouprivate static final String TAG = MyClass.class.getSimpleName();
La seconde est plus conviviale pour le changement de nom de classe globale à l'aide d'un IDE.Je l'utilise pour initier le Log4j Logger en haut de mes classes (ou annoter).
PRO: Throwable est déjà chargé et vous pouvez économiser des ressources en n'utilisant pas le SecurityManager "IO heavy".
CON: Certains se demandent si cela fonctionnera pour toutes les JVM.
la source
Abus du SecurityManager
Ou, s'il n'est pas défini, utilisez une classe interne qui l'étend (exemple ci-dessous copié honteusement à partir de HowTo de Real ):
la source
Si vous voulez le nom complet du package avec lui, appelez:
Si vous ne voulez que le dernier élément, appelez:
la source
L'utilisation verbatim de la classe de l'appelant
MyClass.class.getName()
fait le travail, mais est sujette à des erreurs de copier / coller si vous propagez ce code à de nombreuses classes / sous-classes où vous avez besoin de ce nom de classe.Et la recette de Tom Hawtin n'est en fait pas mauvaise, il suffit de la faire cuire correctement :)
Dans le cas où vous avez une classe de base avec une méthode statique qui peut être appelée à partir de sous-classes, et cette méthode statique doit connaître la classe de l'appelant réel, cela peut être réalisé comme suit:
la source
Une solution sûre pour le refactoring, coupe-coller qui évite la définition des classes ad-hoc ci-dessous.
Écrivez une méthode statique qui récupère le nom de la classe en prenant soin d'inclure le nom de la classe dans le nom de la méthode:
puis rappelez-le dans votre méthode statique:
La refactorisation de la sécurité est donnée en évitant l'utilisation de chaînes, la sécurité de copier-coller est accordée car si vous coupez et collez la méthode de l'appelant, vous ne trouverez pas le getMyClassName () dans la classe cible "MyClass2", vous serez donc obligé de le redéfinir et de le mettre à jour.
la source
Depuis la question Quelque chose comme «this.class» au lieu de «ClassName.class»? est marqué comme un doublon pour celui-ci (ce qui est défendable car cette question concerne la classe plutôt que le nom de la classe), je poste la réponse ici:
Il est important de définir
thisClass
comme privé car:1) il ne doit pas être hérité: les classes dérivées doivent soit définir les leurs,
thisClass
soit produire un message d'erreur2) les références à partir d'autres classes doivent être faites comme
ClassName.class
plutôt queClassName.thisClass
.Avec
thisClass
défini, l'accès au nom de classe devient:la source
J'avais besoin du nom de classe dans les méthodes statiques de plusieurs classes, j'ai donc implémenté une classe JavaUtil avec la méthode suivante:
J'espère que cela vous aidera!
la source
J'ai utilisé ces deux approches pour les deux
static
et lenon static
scénario:Classe principale:
Comment fournir le nom de la classe:
manière non statique:
Manière statique:
la source
Si vous utilisez la réflexion, vous pouvez obtenir l'objet Method puis:
Pour obtenir la méthode elle-même, vous pouvez probablement utiliser:
la source
Class.forName("class name")
déjà donné un cours. Pourquoi voulez-vous le récupérer via la méthode?