Class.forName () vs ClassLoader.loadClass () – à utiliser pour le chargement dynamic?

Lorsque vous chargez dynamicment une classe, quand convient-il d’utiliser

Class.forName("SomeClass"); 

et quand devrais-je utiliser

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

Ou sont-ils deux façons de faire la même chose?

Ils sont assez différents!

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

Renvoie l’object Class 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 référence à voulez-vous initialiser la classe? )

D’autre part, ClassLoader.loadClass(Ssortingng) :

Invoquer cette méthode équivaut à invoquer loadClass(name, false) .

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

Le premier ( Class.forName("SomeClass"); ) va:

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

L’autre ( ClassLoader.getSystemClassLoader().loadClass("SomeClass"); ) va:

  • utiliser le chargeur de classe “system” ( qui est remplaçable )
  • ne pas initialiser la classe (par exemple, si vous l’utilisez pour charger un pilote JDBC, il ne sera pas enregistré et vous ne pourrez pas utiliser JDBC!)

Supposons que vous codez une application Web qui sera exécutée sur un conteneur tel que Tomcat. Tomcat crée un chargeur de classe pour chaque application Web (de sorte qu’il puisse décharger les applications Web plus tard et libérer de la mémoire – vous avez besoin d’un chargeur de classe 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 et 12.4 de la dernière (3ème) édition de la spécification de langage Java.

Class.forName() utilise le chargeur de classes de l’appelant et initialise la classe (exécute des intitiales statiques, etc.)

loadClass est une méthode ClassLoader , elle utilise donc un chargeur fourni explicitement et initialise la classe paresseusement (lors de la première utilisation).

Notez qu’il existe un Class.forName () qui prend également un ClassLoader .

Ils font essentiellement la même chose. Le ClassLoader utilisé peut être différent cependant. 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 système.

Dans la plupart des applications, ce sera le même chargeur de classe mais dans des environnements plus compliqués tels qu’une application J2EE ou une applet, cela peut ne pas être le cas.

ClassLoader est une classe abstraite, cependant votre application est toujours chargée par un chargeur de classe, il peut y avoir des chargeurs de classes personnalisés tels que le chargeur de classe réseau ou toute autre source.

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

Voici la source de Class.forName qui invoque à son tour le chargeur de classe appelant.

 public static Class forName(Ssortingng 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.Ssortingng )

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

  • Class.forName() charge et initialise la classe. Dans le sous-système du chargeur de classe, il exécute les trois phases, à savoir charger, lier et initialiser les phases.

  • ClassLoader.loadClass() , qui retarde l’initialisation jusqu’à ce que la classe soit utilisée pour la première fois. Dans le sous-système du chargeur de classes, il n’exécute que deux phases, à savoir les phases de chargement et de liaison.

Par exemple:

 class MyClass { static { System.out.println("static block in MyClass"); } } public class TestCase1 { public static void main(Ssortingng... args) throws Throwable { Class.forName("A"); } } //The above TestCase1 produce output: static block in MyClass public class TestCase2 { public static void main(Ssortingng... args) throws Throwable { ClassLoader.getSystemClassLoader().loadClass("MyClass"); } } //The above TestCase2 not produce any output 

J’adore le chargement en classe en java …

Cela dépend vraiment du contexte dans lequel l’application est exécutée. Vous obtiendrez des résultats différents si vous l’utilisez depuis un contexte Web plutôt que vers un programme en ligne de commande.

J’ai également rencontré des problèmes en fonction de l’aspect de votre ClassPath et de ce que j’attendais.

Cet article de JavaWorld en explique beaucoup.