60 votes

Comment fonctionne Class.forName() ?

Je viens d'apprendre que java.sql package . Il utilise Class.forName() pour charger dynamiquement le pilote qui étend DriverManager . Ensuite, nous obtenons la connexion en utilisant DriverManager.getConnection() méthode.

Alors comment ça marche ?
Comment la classe DriverManager sait-elle comment obtenir la connexion sans utiliser le nom de la classe du pilote réel ?

De même, pouvons-nous utiliser Class.forName() pour des applications personnalisées... si cela est expliqué avec un exemple, je serai très heureux.

0 votes

74voto

Jon Skeet Points 692016

Class.forName charge simplement une classe, y compris l'exécution de ses initialisateurs statiques, comme ceci :

class Foo {
    static {
        System.out.println("Foo initializing");
    }
}

public class Test {
    public static void main(String [] args) throws Exception {
        Class.forName("Foo");
    }
}

Tout le reste de la procédure dont vous parlez est spécifique à JDBC. Le pilote - qui implémente Driver il ne s'étend pas DriverManager - enregistre simplement une instance appropriée en utilisant DriverManager.registerDriver . Ensuite, lorsque DriverManager a besoin de trouver un pilote pour une chaîne de connexion particulière, il appelle connect sur chaque pilote enregistré à tour de rôle jusqu'à ce qu'il réussisse et renvoie une connexion non nulle.

Notez que cette façon d'enregistrer les pilotes est relativement démodée - regardez les docs de DriverManager pour des moyens plus modernes d'accéder à une source de données.

29voto

Shubham Verma Points 546

Lorsque nous créons un instace d'une classe en utilisant l'opérateur new, il fait deux choses

  1. Charger la classe dans la mémoire, si elle n'est pas chargée. ce qui signifie créer une représentation en mémoire de la classe à partir du fichier .class afin qu'une instance puisse être créée à partir de celle-ci. Cela inclut l'initialisation des variables statiques (résolution de cette classe).
  2. créer une instance de cette classe et stocker la référence à la variable.

Class.forName ne fait que la première chose. Il charge la classe en mémoire et renvoie cette référence comme une instance de Class. Si nous voulons créer une instance, nous pouvons appeler la méthode newInstance de cette classe, qui invoquera le constructeur par défaut (constructeur sans argument). Notez que si le constructeur par défaut n'est pas accessible, alors la méthode newInstance lèvera une erreur de type IllegalAccessException . et si la classe est une classe abstraite ou une interface ou si elle n'a pas de constructeur par défaut, alors elle lancera un InstantiationException . Si une exception survient au cours de la résolution de cette classe, elle lancera un ExceptionInInitializerError .

Si le constructeur par défaut n'est pas défini, nous devons alors invoquer le constructeur défini en utilisant l'API de réflexion.

Mais le principal avantage de Class.forName est qu'il peut accepter le nom de la classe comme argument de type String. Nous pouvons donc passer le nom de la classe de façon dynamique. Mais si nous créons une instance d'une classe en utilisant l'opérateur new, le nom de la classe ne peut pas être modifié dynamiquement.

Class.forName() appellera à son tour la méthode loadClass de l'appelant ClassLoader (ClassLoder de la classe d'où provient l'élément Class.forName est invoquée).

Par défaut, le Class.forName() résoudre cette classe. ce qui signifie, initialiser toutes les variables statiques à l'intérieur de cette classe. La même chose peut être modifiée en utilisant la méthode surchargée de Class.forName(String name,boolean initialize,ClassLoader loader)

La raison principale pour charger le driver jdbc en utilisant Class.forName() c'est que le conducteur peut changer dynamiquement. Dans le bloc statique, tous les pilotes créeront une instance d'eux-mêmes et enregistreront cette classe auprès du DriverManager en utilisant les éléments suivants DriverManager.registerDriver() méthode. Puisque la Class.forName(String className) par défaut résoudre la classe, elle va initialiser l'initialisateur statique. Ainsi, lorsque nous appelons Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver") , la classe Driver sera chargée, instanciée et enregistrée avec DriverManager.

Donc si vous utilisez le nouvel opérateur, vous devez faire les choses suivantes.
Code :

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver();
DriverManager.registerDriver(drv);

17voto

Bozho Points 273663

Class.forName(..) charge et initialise la classe cible. Cela signifie à son tour que les blocs d'initialisation statiques sont invoqués (le code défini dans le fichier static { .. } .

Si vous regardez, par exemple, le pilote de MySQL, dans ce bloc statique, le pilote s'enregistre lui-même : DriverManager.registerDriver(new Driver());

Vous pouvez omettre le Class.forName(..) et enregistrez le pilote vous-même si vous pouvez vous "permettre" de dépendre du pilote MySQL au moment de la compilation.

Cela dit, il sera rarement pertinent d'utiliser Class.forName(..) pour initialiser les classes de votre application, car la dépendance au moment de la compilation n'est pas un problème ici.

Notez également que Class.forName(..) n'est plus nécessaire pour JDBC depuis la version 4. En utilisant le fournisseur de services vous pouvez indiquer au gestionnaire de pilotes ce qu'il doit charger par une propriété système.

4voto

La raison pour laquelle Class.forName() est fréquemment mentionnée dans les exemples SQL, c'est parce qu'il n'y avait pas de magie pour dire au DriverManager JDBC comment pour faire correspondre l'URL JDBC fournie à un pilote réel.

Par exemple, "mysql" doit correspondre à une classe MySQL donnée, "thin" correspond à la classe Oracle, "as400" correspond à la classe DB2/400.

En chargeant explicitement la classe, cela permet d'exécuter le code de la classe qui s'enregistre auprès du DriverManager.

De nos jours, les crochets magiques sont présents et permettent à la JVM de découvrir automatiquement les pilotes (s'ils sont suffisamment nouveaux), de sorte que l'appel est superflu, mais par habitude, beaucoup l'utilisent encore.

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