Réponses:
Peut-être qu'un exemple montrant comment les deux méthodes sont utilisées vous aidera à mieux comprendre les choses. Alors, considérez la classe suivante:
package test;
public class Demo {
public Demo() {
System.out.println("Hi!");
}
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("test.Demo");
Demo demo = (Demo) clazz.newInstance();
}
}
Comme expliqué dans son javadoc, l'appel renvoie l' objet associé à la classe ou à l'interface avec le nom de chaîne donné, c'est-à-dire qu'il renvoie ce qui est affecté à la variable de type .Class.forName(String)
Class
test.Demo.class
clazz
Class
Ensuite, l'appel crée une nouvelle instance de la classe représentée par cet objet. La classe est instanciée comme par une expression avec une liste d'arguments vide. En d'autres termes, c'est ici en fait équivalent à a et renvoie une nouvelle instance de .clazz.newInstance()
Class
new
new Demo()
Demo
Et exécuter cette Demo
classe imprime ainsi la sortie suivante:
Hi!
La grande différence avec le traditionnel new
est que cela newInstance
permet d'instancier une classe que vous ne connaissez pas avant l'exécution, ce qui rend votre code plus dynamique.
Un exemple typique est l'API JDBC qui charge, au moment de l'exécution, le pilote exact requis pour effectuer le travail. Les conteneurs EJB, les conteneurs Servlet sont d'autres bons exemples: ils utilisent le chargement dynamique à l'exécution pour charger et créer des composants dont ils ne savent rien avant l'exécution.
En fait, si vous voulez aller plus loin, jetez un œil à l'article de Ted Neward Understanding Class.forName () que je paraphrasais dans le paragraphe juste au-dessus.
EDIT (répondant à une question de l'OP postée en commentaire): Le cas des pilotes JDBC est un peu particulier. Comme expliqué dans le chapitre DriverManager de Premiers pas avec l'API JDBC :
(...) Une
Driver
classe est chargée, et donc automatiquement enregistrée avec leDriverManager
, de l'une des deux manières suivantes:
en appelant la méthode
Class.forName
. Cela charge explicitement la classe de pilote. Comme il ne dépend d'aucune configuration externe, cette façon de charger un pilote est celle recommandée pour l'utilisation duDriverManager
framework. Le code suivant charge la classeacme.db.Driver
:Class.forName("acme.db.Driver");
Si
acme.db.Driver
a été écrit de façon à ce que le chargement provoque la création d'une instance et appelle égalementDriverManager.registerDriver
cette instance comme paramètre (comme il se doit), alors il est dans laDriverManager
liste des pilotes et disponible pour créer une connexion.(...)
Dans ces deux cas, il est de la responsabilité de la
Driver
classe nouvellement chargée de s'enregistrer en appelantDriverManager.registerDriver
. Comme mentionné, cela devrait être fait automatiquement lorsque la classe est chargée.
Pour s'enregistrer lors de l'initialisation, le pilote JDBC utilise généralement un bloc d'initialisation statique comme celui-ci:
package acme.db;
public class Driver {
static {
java.sql.DriverManager.registerDriver(new Driver());
}
...
}
L'appel Class.forName("acme.db.Driver")
provoque l'initialisation de la acme.db.Driver
classe et donc l'exécution du bloc d'initialisation statique. Et Class.forName("acme.db.Driver")
va effectivement "créer" une instance, mais ce n'est qu'une conséquence de la façon dont les (bons) pilotes JDBC sont implémentés.
En remarque, je mentionnerais que tout cela n'est plus nécessaire avec JDBC 4.0 (ajouté comme package par défaut depuis Java 7) et la nouvelle fonctionnalité de chargement automatique des pilotes JDBC 4.0. Voir les améliorations de JDBC 4.0 dans Java SE 6 .
DriverManager.registerDriver
. L'appel Class.forName
sur un pilote JDBC provoque son initialisation et donc l'exécution du bloc statique. Jetez un œil à java2s.com/Open-Source/Java-Document/Database-DBMS/… pour un exemple. C'est donc un cas particulier en raison des composants internes du pilote.
Class.forName () vous donne l'objet de classe, ce qui est utile pour la réflexion. Les méthodes de cet objet sont définies par Java, pas par le programmeur qui écrit la classe. Ils sont les mêmes pour chaque classe. Appeler newInstance () sur cela vous donne une instance de cette classe (c'est-à-dire que l'appeler Class.forName("ExampleClass").newInstance()
équivaut à appeler new ExampleClass()
), sur laquelle vous pouvez appeler les méthodes que la classe définit, accéder aux champs visibles, etc.
Dans le monde JDBC, la pratique normale (selon l'API JDBC) est que vous utilisez Class#forName()
pour charger un pilote JDBC. Le pilote JDBC doit notamment s'enregistrer dans DriverManager
un bloc statique:
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class MyDriver implements Driver {
static {
DriverManager.registerDriver(new MyDriver());
}
public MyDriver() {
//
}
}
L'appel Class#forName()
exécutera tous les initialiseurs statiques . De cette façon, vous DriverManager
pouvez trouver le pilote associé parmi les pilotes enregistrés par URL de connexion au cours de getConnection()
laquelle ressemblent à peu près à ce qui suit:
public static Connection getConnection(String url) throws SQLException {
for (Driver driver : registeredDrivers) {
if (driver.acceptsURL(url)) {
return driver.connect(url);
}
}
throw new SQLException("No suitable driver");
}
Mais il y avait aussi bogué pilotes JDBC, en commençant par l' org.gjt.mm.mysql.Driver
exemple aussi bien connu, qui s'enregistre de manière incorrecte à l' intérieur du constructeur au lieu d'un bloc statique:
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class BadDriver implements Driver {
public BadDriver() {
DriverManager.registerDriver(this);
}
}
La seule façon de le faire fonctionner dynamiquement est d'appeler newInstance()
après! Sinon, vous serez confronté à première vue "SQLException inexplicable: pas de pilote approprié". Encore une fois, il s'agit d'un bogue dans le pilote JDBC, pas dans votre propre code. De nos jours, aucun pilote JDBC ne devrait contenir ce bogue. Ainsi, vous pouvez (et devriez) laisser de newInstance()
côté.
1: si vous êtes intéressé uniquement par le bloc statique de la classe, le chargement de la classe ne ferait que faire, et exécuterait des blocs statiques alors tout ce dont vous avez besoin est:
Class.forName("Somthing");
2: si vous êtes intéressé par le chargement de la classe, exécutez ses blocs statiques et souhaitez également accéder à sa partie non statique, alors vous avez besoin d'une instance et vous avez besoin de:
Class.forName("Somthing").newInstance();
"Class.forName ()" renvoie le type de classe pour le nom donné. "newInstance ()" renvoie une instance de cette classe.
Sur le type, vous ne pouvez appeler directement aucune méthode d'instance, mais vous pouvez uniquement utiliser la réflexion pour la classe. Si vous voulez travailler avec un objet de la classe, vous devez en créer une instance (comme pour appeler "new MyClass ()").
Exemple pour "Class.forName ()"
Class myClass = Class.forName("test.MyClass");
System.out.println("Number of public methods: " + myClass.getMethods().length);
Exemple pour "Class.forName (). NewInstance ()"
MyClass myClass = (MyClass) Class.forName("test.MyClass").newInstance();
System.out.println("String representation of MyClass instance: " + myClass.toString());
en ajoutant simplement aux réponses ci-dessus, lorsque nous avons un code statique (c'est-à-dire que le bloc de code est indépendant de l'instance) qui doit être présent en mémoire, nous pouvons avoir la classe retournée donc nous utiliserons Class.forname ("someName") sinon si nous ne pas avoir de code statique, nous pouvons utiliser Class.forname (). newInstance ("someName") car il chargera des blocs de code de niveau objet (non statiques) en mémoire
Peu importe le nombre de fois que vous appelez la méthode Class.forName (), Une fois que le bloc statique est exécuté, pas plusieurs fois:
package forNameMethodDemo;
classe publique MainClass {
public static void main(String[] args) throws Exception {
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
DemoClass demoClass = (DemoClass)Class.forName("forNameMethodDemo.DemoClass").newInstance();
}
}
public class DemoClass {
static {
System.out.println("in Static block");
}
{
System.out.println("in Instance block");
}
}
la sortie sera:
in Static block
in Instance block
Cette in Static block
déclaration est imprimée une seule fois pas trois fois.
Class.forName () -> forName () est la méthode statique de la classe Class, elle retourne un objet de classe Class utilisé pour la réflexion et non un objet de classe utilisateur, vous ne pouvez donc appeler que des méthodes de classe Class comme getMethods (), getConstructors () etc.
Si vous vous souciez d'exécuter uniquement le bloc statique de votre classe (Runtime donné) et d'obtenir uniquement des informations sur les méthodes, les constructeurs, le modificateur, etc. de votre classe, vous pouvez le faire avec cet objet que vous obtenez en utilisant Class.forName ()
Mais si vous voulez accéder ou appeler votre méthode de classe (classe que vous avez donnée au moment de l'exécution), vous devez avoir son objet afin que la méthode newInstance de la classe Class le fasse pour vous.Il crée une nouvelle instance de la classe et vous la renvoie Il vous suffit de le transtyper dans votre classe.
ex-: supposons que l'employé soit votre classe alors
Classe a = Class.forName (args [0]);
// args [0] = argument de ligne cmd pour donner la classe à l'exécution.
Employé ob1 = a.newInstance ();
a.newInstance () est similaire à la création d'un objet à l'aide de new Employee ().
vous pouvez maintenant accéder à tous les champs et méthodes visibles de votre classe.