269 votes

Obtenir le nom de la classe à partir d'une méthode statique en Java

Comment peut-on obtenir le nom de la classe à partir d'une méthode statique de 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 remettre les choses dans leur contexte, je veux en fait renvoyer le nom de la classe dans le cadre d'un message dans une exception.

2 votes

try{ throw new RuntimeEsception();} catch(RuntimeEcxeption e){return e.getstackTrace()[1].getClassName(); }

241voto

toolkit Points 27248

Afin de supporter correctement le refactoring (renommer une classe), vous devez utiliser l'un ou l'autre :

 MyClass.class.getName(); // full name with package

ou (grâce à @James Van Huis ) :

 MyClass.class.getSimpleName(); // class name and no more

147 votes

Si vous devez coder en dur la connaissance de MyClass comme ça, alors vous pourriez aussi bien faire String name = "MyClass" ; !

114 votes

Mais alors, le remaniement du nom de la classe dans votre IDE ne fonctionnera pas correctement.

9 votes

Vrai. Bien que MyClass.class permette de s'assurer que cette ligne ne sera pas oubliée lors d'un remaniement de type "changer le nom de la classe".

121voto

Faites ce que @toolkit dit. Ne faites rien de tel :

return new Object() { }.getClass().getEnclosingClass();

( Edit : Ou si vous utilisez une version de Java qui est sortie bien après la rédaction de cette réponse, @Rein).

7 votes

Si la classe en étend une autre, cela ne renvoie pas la classe actuelle, mais seulement la classe de base.

1 votes

@LuisSoeiro Je crois que cela renvoie la classe dans laquelle la méthode est définie. Je ne suis pas sûr de la manière dont la classe de base est prise en compte dans le contexte statique.

8 votes

Je ne comprends pas pourquoi getClass() ne peut pas être statique. Cet "idiome" ne serait alors pas nécessaire.

41voto

Keksi Points 241

Cette instruction fonctionne bien :

Thread.currentThread().getStackTrace()[1].getClassName();

5 votes

Attention, cela peut être très lent. Cependant, vous pouvez le copier-coller.

1 votes

Cela présente l'avantage supplémentaire de ne pas devoir créer un objet ou un fil à chaque fois que vous l'utilisez.

5 votes

@ErelSegalHalevi Ça crée un tas de StackTraceElement s en arrière-plan :(

35voto

lifelongcoug Points 361

Vous pourriez faire quelque chose de vraiment sympa en utilisant JNI comme ceci :

MyObject.java :

public class MyObject
{
    static
    {
        System.loadLibrary( "classname" );
    }

    public static native String getClassName();

    public static void main( String[] args )
    {
        System.out.println( getClassName() );
    }
}

alors :

javac MyObject.java
javah -jni MyObject

alors :

MyObject.c :

#include "MyObject.h"

JNIEXPORT jstring JNICALL Java_MyObject_getClassName( JNIEnv *env, jclass cls )
{
    jclass javaLangClass = (*env)->FindClass( env, "java/lang/Class" );
    jmethodID getName = (*env)->GetMethodID( env, javaLangClass, "getName",
        "()Ljava/lang/String;" );
    return (*env)->CallObjectMethod( env, cls, getName );
}

Ensuite, compilez le C dans une bibliothèque partagée appelée libclassname.so et lancez la java !

*chuckle

0 votes

Pourquoi cela n'est-il pas intégré ?

0 votes

Intelligent, et j'apprécie l'humour. Le hic, c'est que le nom par défaut de la fonction C Java_MyObject_getClassName a le nom incorporé. Le moyen de contourner ce problème est d'utiliser la fonction JNI RegisterNatives . Bien sûr, vous devrez alimenter cela avec la JNI. FindClass(env, 'com/example/MyObject') donc pas de victoire là non plus.

2 votes

@Renate, donc toute cette réponse est en fait une blague ? Si c'est le cas, merci de le préciser car vous savez, nous sommes censés aider les autres, alors ne poussons pas les innocents dans des pièges.

21voto

count ludwig Points 171

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 "lourd en IO".

CON : On peut se demander si cela fonctionnera pour toutes les JVM.

// Log4j . Logger --- Get class name in static context by creating an anonymous Throwable and 
// getting the top of its stack-trace. 
// NOTE you must use: getClassName() because getClass() just returns StackTraceElement.class 
static final Logger logger = Logger.getLogger(new Throwable() .getStackTrace()[0].getClassName());

0 votes

Créez votre propre classe d'exception pour que le jvm ne s'en préoccupe pas : jhocr.googlecode.com/svn/trunk/src/main/java/com/googlecode/

1 votes

Si vous devez suggérer quelque chose d'aussi horrible que cette solution, veuillez au moins faire le lien entre vos pour et la solution naturelle consistant à utiliser MyClass.class.getName(), au lieu d'une autre solution horrible comme l'abus du SecurityManager.

0 votes

Plus d'inconvénients : trop verbeux ; lent (c'est en fait un point mineur car il ne s'exécute qu'une seule fois, lorsque la classe est chargée).

Prograide.com

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.

Powered by:

X