Existe-t-il un moyen d'instancier une classe par son nom en Java?

102

Je cherchais comme question: instancier une classe à partir de son nom de chaîne qui décrit comment instancier une classe en ayant son nom. Existe-t-il un moyen de le faire en Java? J'aurai le nom du package et le nom de la classe et je dois être capable de créer un objet portant ce nom particulier.

ict1991
la source
Nous instancions une classe et le résultat est un objet (ou: instance ).
Andreas Dolk
1
La réponse est oui, mais je pense que vous devriez demander si c'est une bonne idée. Avec une grande puissance (réflexion) vient une grande responsabilité et vous ne devriez l'utiliser que si vous comprenez et avez considéré les conséquences.
c1moore

Réponses:

239

Deux manières:

Méthode 1 - uniquement pour les classes ayant un constructeur sans argument

Si votre classe a un constructeur sans argument, vous pouvez obtenir un Classobjet en utilisant Class.forName()et utiliser la newInstance()méthode pour créer une instance (mais attention, cette méthode est souvent considérée comme mauvaise car elle peut vaincre les exceptions vérifiées par Java).

Par exemple:

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

Méthode 2

Une approche alternative plus sûre qui fonctionne également si la classe n'a pas de constructeur sans argument consiste à interroger votre objet de classe pour obtenir son Constructorobjet et appeler une newInstance()méthode sur cet objet:

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

Les deux méthodes sont appelées réflexion . Vous devrez généralement attraper les différentes exceptions qui peuvent se produire, y compris des choses comme:

  • la JVM ne trouve pas ou ne peut pas charger votre classe
  • la classe que vous essayez d'instancier n'a pas le bon type de constructeurs
  • le constructeur lui-même a lancé une exception
  • le constructeur que vous essayez d'appeler n'est pas public
  • un gestionnaire de sécurité a été installé et empêche la réflexion de se produire
Simon Nickerson
la source
salut, une fois que nous avons créé l'objet à partir de newInstance(), pourrions-nous le renvoyer à notre propre objet?
GMsoF
@Simon pouvez-vous élaborer / donner un pointeur sur le responsable de la sécurité?
Ram
Je ne comprends pas ça. Je veux accéder à une classe dans un fichier inconnu dans un autre répertoire, je n'ai que le nom du chemin / fichier sous forme de chaîne. Chaîne "dir / unkonwn.java". L'appel de Class.forName ("dir / unknown") me donne des erreurs.
john ktejik
Comment pouvons - nous jeter instanceà com.foo.MyClass? étant donné que com.foo.MyClass est juste une chaîne
Sanket9394
14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
scibuff
la source
15
Il convient de mentionner que cela ne fonctionne pas si la classe n'a pas de constructeur sans paramètre (et a d'autres constructeurs), ou si le constructeur sans paramètre est inaccessible.
Dawood ibn Kareem
3

use Class.forName ("String name of class"). newInstance ();

Class.forName("A").newInstance();

Cela entraînera l'initialisation de la classe nommée A.

Chandra Sekhar
la source
Ne fonctionne pas pour moi, même avec le nom du package ajouté. :(
trusktr
3

Pour faciliter l'obtention du nom complet d'une classe afin de créer une instance en utilisant Class.forName(...), on pourrait utiliser la Class.getName()méthode. Quelque chose comme:

class ObjectMaker {
    // Constructor, fields, initialization, etc...
    public Object makeObject(Class<?> clazz) {
        Object o = null;

        try {
            o = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            // There may be other exceptions to throw here, 
            // but I'm writing this from memory.
            e.printStackTrace();
        }

        return o;
    }
}

Ensuite, vous pouvez convertir l'objet que vous récupérez dans la classe à laquelle vous passez makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);
Roberto
la source
1
Ne pouvez-vous pas simplement clazz.newInstance()au lieu du getNamealors fromName?
user276648
1

Utiliser la réflexion Java

Création de nouveaux objets Il n'y a pas d'équivalent à l'invocation de méthode pour les constructeurs, car appeler un constructeur équivaut à créer un nouvel objet (pour être le plus précis, la création d'un nouvel objet implique à la fois l'allocation de mémoire et la construction d'objet). Donc, l'équivalent le plus proche de l'exemple précédent est de dire:

import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

qui trouve un constructeur qui gère les types de paramètres spécifiés et l'appelle, pour créer une nouvelle instance de l'objet. La valeur de cette approche est qu'elle est purement dynamique, avec une recherche et un appel de constructeur au moment de l'exécution, plutôt qu'au moment de la compilation.

Kornero
la source
1

Class.forName ("ClassName") résoudra votre objectif.

Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
Balaswamy Vaddeman
la source
0
String str = (String)Class.forName("java.lang.String").newInstance();
Chen Harel
la source
0

quelque chose comme ça devrait fonctionner ...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();
Shashank Kadne
la source
0

L'utilisation newInstance()directe est déconseillée à partir de Java 8. Vous devez l'utiliser Class.getDeclaredConstructor(...).newInstance(...)avec les exceptions correspondantes.

Mel
la source