103 votes

Class.forName() vs ClassLoader.loadClass() - lequel utiliser pour le chargement dynamique ?

Lors du chargement dynamique d'une classe, quand est-il approprié d'utiliser la fonction

Class.forName("SomeClass");

et quand dois-je utiliser

ClassLoader.getSystemClassLoader().loadClass("SomeClass");

Ou bien, s'agit-il de deux façons de faire la même chose ?

168voto

Bruno Reis Points 16132

Ils sont très différents !

Comme indiqué dans la documentation de Class.forName(String) ,

Renvoie l'objet Classe associé à la classe ou à l'interface avec le nom de chaîne donné. L'appel de cette méthode est équivalent à : Class.forName(className, true, currentLoader)

( true fait ici référence à voulez-vous initialiser la classe ? )

D'un autre côté, ClassLoader.loadClass(String) :

L'appel de cette méthode est équivalent à l'appel de loadClass(name, false) .

(ici, le booléen n'a rien à voir avec l'initialisation ; mais si vous consultez la documentation de loadClass(String, boolean), vous verrez que tout ce qu'il fait est de charger la classe, et non de l'initialiser).

Le premier ( Class.forName("SomeClass"); ) le fera :

  • utiliser le chargeur de classe qui a chargé la classe qui appelle ce code
  • initialiser la classe (c'est-à-dire que tous les initialisateurs statiques seront exécutés)

L'autre ( ClassLoader.getSystemClassLoader().loadClass("SomeClass"); ) le fera :

  • utiliser le chargeur de classes "système" ( qui peut être remplacé par )
  • ne pas initialiser la classe (par exemple, si vous l'utilisez pour charger un pilote JDBC, elle ne sera pas enregistrée, et vous ne pourrez pas utiliser JDBC !)

Supposons que vous codiez une application web qui sera exécutée sur un conteneur tel que Tomcat. Tomcat crée un chargeur de classes pour chaque application Web (afin de pouvoir décharger les applications Web ultérieurement et libérer de la mémoire - il faut un chargeur de classes dédié pour que cela fonctionne !) Dans cette situation, vous pouvez voir que les deux appels donneront des résultats très différents !

Pour des informations plus détaillées (et faisant autorité) sur le chargement et l'initialisation des classes, consultez les sections 12.2 y 12.4 de la dernière (3ème) édition de la spécification du langage Java.

10voto

Dave Newton Points 93112

Class.forName() utilise le classloader de l'appelant et initialise la classe (exécute les initialisateurs statiques, etc.)

loadClass est un ClassLoader il utilise donc un chargeur fourni explicitement et initialise la classe paresseusement (à la première utilisation).

Notez qu'il y a un Classe.forName() qui prend également un ClassLoader .

0voto

Sarel Botha Points 5911

Ils font fondamentalement la même chose. Le ClassLoader utilisé peut cependant être différent. Class.forName utilise le ClassLoader que vous obtenez de this.getClass().getClassLoader() alors que votre autre code spécifie d'utiliser le chargeur de classe du système.

Dans la plupart des applications, il s'agira du même chargeur de classes, mais dans des environnements plus complexes, comme une application J2EE ou une applet, ce ne sera pas forcément le cas.

0voto

Bax Points 643

-1voto

r0ast3d Points 2443

ClassLoader est une classe abstraite, cependant votre application est toujours chargée par un classloader, il peut y avoir des classloaders personnalisés comme le network classloader ou toute autre source.

D'autre part, la classe en elle-même représente les classes et les interfaces et la classe Class possède une fonction forName qui utilise le chargeur de classe actuel dans lequel votre application est exécutée par défaut pour charger la classe.

Voici la source de Class.forName qui, à son tour, invoque le classloader appelant.

public static Class<?> forName(String className)
            throws ClassNotFoundException {
    return forName0(className, true, ClassLoader.getCallerClassLoader());
}

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html

http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#forName(java.lang.String

Indice : le chargeur de classe Primordial http://docs.oracle.com/javase/1.4.2/docs/guide/security/spec/security-spec.doc5.html

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