HOWTO · Java

Obtenir le nom de la classe en Java

Cet article montre comment obtenir le nom de la classe en Java

Sur cette page

Pour obtenir le nom d’une classe Java, commencez par choisir la représentation dont vous avez besoin. Appelez getClass() sur un objet pour obtenir son objet Class<?> à l’exécution, puis appelez getSimpleName(), getName() ou getCanonicalName() sur cette classe. Utilisez un littéral de classe, comme String.class, lorsque le type est déjà connu. Les trois méthodes de nom donnent des résultats différents pour les classes imbriquées et spéciales : ils ne sont donc pas interchangeables.

Choisir la représentation du nom de classe adaptée

Utilisez getSimpleName() pour obtenir un nom d’affichage concis, getName() pour le nom binaire de la JVM et getCanonicalName() pour le nom canonique de style source, lorsqu’il existe. Le nom simple omet le paquetage. Le nom binaire peut inclure le préfixe du paquetage et des séparateurs $ pour les types imbriqués. Le nom canonique sépare par des points les classes englobantes et imbriquées, mais n’est pas disponible pour toutes les classes et peut valoir null.

Ces valeurs sont des noms, et non des objets Class. Elles sont utiles pour l’affichage, le diagnostic et l’inspection liée à la réflexion, mais n’utilisez pas un nom généré comme identifiant stable pour la persistance ou des protocoles externes. Si vous connaissez déjà le type à la compilation, un littéral de classe vous évite de rechercher d’abord une instance.

Obtenir la classe d’exécution d’un objet avec getClass()

getClass() est une méthode d’instance héritée de Object. Elle renvoie la classe réelle de l’objet à l’exécution sous la forme d’un Class<?> ; elle ne renvoie pas une chaîne. C’est utile lorsque le type déclaré d’une variable est plus général que celui de l’objet auquel elle fait référence. Par exemple, une variable déclarée comme Object permet tout de même d’obtenir la classe d’exécution de sa valeur actuelle.

Exécutez cet exemple :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

public class ClassNameExample {
    public static void main(String[] args) {
        Object value = "hello";
        Class<?> runtimeClass = value.getClass();

        System.out.println(runtimeClass.getSimpleName());
        System.out.println(runtimeClass.getName());
    }
}
String
java.lang.String

La première ligne demande un nom simple lisible ; la seconde demande le nom binaire. Cet exemple utilise la classe d’exécution de la valeur, qui est String, plutôt que le type déclaré de la variable value (Object). Lorsque le type est déjà connu, String.class fournit son objet Class<String> sans qu’il soit nécessaire de créer une instance de chaîne. Les valeurs affichées dans le bloc de sortie restent en anglais.

Choisir entre getSimpleName(), getName() et getCanonicalName()

Appelez chaque méthode de nom sur un objet Class<?>. Pour une classe de premier niveau comme java.util.ArrayList, getSimpleName() renvoie ArrayList, tandis que getName() et getCanonicalName() renvoient java.util.ArrayList. Pour une classe membre Outer.Inner, le nom simple est Inner ; le nom binaire sépare les classes par un $, tandis que le nom canonique utilise un point.

Méthode Utilisation Forme courante
getSimpleName() Affichage concis ArrayList
getName() Nom binaire de la JVM java.util.ArrayList
getCanonicalName() Nom de style source, lorsqu’il existe java.util.ArrayList

Le préfixe du paquetage apparaît lorsque la classe appartient à un paquetage nommé ; les classes du paquetage par défaut n’en ont pas. getName() ne fournit pas toujours un nom source pleinement qualifié : les classes de tableaux utilisent des descripteurs de style JVM, et les classes locales ou anonymes ont des noms binaires générés. getCanonicalName() peut renvoyer null pour les classes locales et anonymes. Choisissez la méthode en fonction de l’usage prévu de la chaîne, sans supposer qu’une méthode fournit toujours un nom pleinement qualifié.

Un littéral de classe fonctionne avec ces mêmes méthodes. Par exemple, String.class.getSimpleName() renvoie le nom simple du type connu. Pour un objet dont le type n’est connu qu’à l’exécution, appelez d’abord value.getClass().

Gérer les classes anonymes et les autres classes spéciales

Les classes anonymes n’ont pas de nom au niveau du code source. La JVM leur attribue des noms binaires générés, qui contiennent souvent un $ suivi d’un nombre, mais leur forme exacte dépend du compilateur et ne doit pas être considérée comme stable. Pour une classe anonyme, getSimpleName() renvoie une chaîne vide et getCanonicalName() vaut null ; getName() renvoie son nom binaire généré.

Les classes locales sont déclarées dans une méthode ou un initialiseur. Elles ont elles aussi des noms binaires générés, et leur nom canonique vaut null. En revanche, les classes membres sont déclarées comme membres d’une autre classe et ont des noms simple et canonique au niveau du code source. Ces différences expliquent pourquoi une méthode de nom peut renvoyer une valeur vide ou null, même si getClass() identifie correctement la classe d’exécution.

Si un programme a besoin d’un libellé fiable pour une implémentation anonyme ou locale, définissez-le explicitement dans l’application. N’analysez pas un nom généré et n’en déduisez pas un nom de type destiné à l’utilisateur.

Obtenir la classe de l’appelant à partir d’une trace de pile

Vous pouvez examiner une trace de pile lorsque vous devez identifier une frame précise, mais cette approche est moins directe qu’un appel à getClass() sur l’objet concerné. Thread.currentThread().getStackTrace() renvoie un tableau de valeurs StackTraceElement ; getClassName() appliqué à chaque élément renvoie le nom de classe enregistré pour cette frame. La syntaxe suivante montre comment sélectionner une frame, mais l’indice dépend du chemin d’appel et de l’environnement d’exécution. Cet extrait ne permet donc pas d’obtenir de manière portable n’importe quel appelant :

Thread.currentThread().getStackTrace()[2].getClassName()

La méthode en cours et la méthode qui récupère la trace de pile occupent elles aussi des frames ; dans une chaîne d’appels simple, l’indice 2 désigne souvent l’appelant immédiat. Les méthodes enveloppes, les machines virtuelles et les optimisations à l’exécution peuvent modifier les frames présents. Si vous utilisez cette technique à des fins de diagnostic, examinez la liste des frames pour le programme concerné et évitez de parcourir la pile pour obtenir un nom de classe dans les cas courants. Préférez transmettre directement l’objet ou les informations de classe lorsque l’identité de l’appelant fait partie du contrat d’une API.