Gibt es eine Möglichkeit, eine Klasse in Java nach Namen zu instanziieren?

102

Ich habe nach der Frage gesucht: Instanziieren Sie eine Klasse anhand ihres Zeichenfolgennamens, der beschreibt, wie eine Klasse instanziiert wird, wenn sie ihren Namen hat. Gibt es eine Möglichkeit, dies in Java zu tun? Ich habe den Paketnamen und den Klassennamen und muss in der Lage sein, ein Objekt mit diesem bestimmten Namen zu erstellen.

ict1991
quelle
Wir instanziieren eine Klasse und das Ergebnis ist ein Objekt (oder: eine Instanz ).
Andreas Dolk
1
Die Antwort lautet ja, aber ich denke, Sie sollten fragen, ob es eine gute Idee ist. Mit großer Kraft (Reflexion) geht große Verantwortung einher, und Sie sollten sie nur einsetzen, wenn Sie die Konsequenzen verstehen und berücksichtigt haben.
c1moore

Antworten:

238

Zwei Wege:

Methode 1 - nur für Klassen mit einem Konstruktor ohne Argumente

Wenn Ihre Klasse über einen Konstruktor ohne Argumente verfügt, können Sie ein ClassObjekt mithilfe Class.forName()der newInstance()Methode abrufen und zum Erstellen einer Instanz verwenden ( beachten Sie jedoch, dass diese Methode häufig als böse angesehen wird, da sie die überprüften Ausnahmen von Java umgehen kann).

Beispielsweise:

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

Methode 2

Ein alternativer sicherer Ansatz, der auch funktioniert, wenn die Klasse keine Konstruktoren ohne Argumente hat, besteht darin, Ihr Klassenobjekt abzufragen, um sein ConstructorObjekt abzurufen, und eine newInstance()Methode für dieses Objekt aufzurufen :

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

Beide Methoden werden als Reflexion bezeichnet . In der Regel müssen Sie die verschiedenen Ausnahmen abfangen, die auftreten können, einschließlich:

  • Die JVM kann Ihre Klasse nicht finden oder nicht laden
  • Die Klasse, die Sie instanziieren möchten, verfügt nicht über die richtigen Konstruktoren
  • Der Konstruktor selbst hat eine Ausnahme ausgelöst
  • Der Konstruktor, den Sie aufrufen möchten, ist nicht öffentlich
  • Ein Sicherheitsmanager wurde installiert und verhindert das Auftreten von Reflexionen
Simon Nickerson
quelle
Hallo, wenn wir das Objekt erstellt haben newInstance(), können wir es dann auf unser eigenes Objekt zurückwerfen?
GMsoF
@ Simon können Sie den Sicherheitsmanager näher erläutern?
Ram
Ich verstehe das nicht Ich möchte auf eine Klasse in einer unbekannten Datei in einem anderen Verzeichnis zugreifen. Ich habe nur den Namen des Pfads / der Datei als Zeichenfolge. String "dir / unkonwn.java". Das Aufrufen von Class.forName ("dir / unknown") gibt mir Fehler.
John Ktejik
Wie können wir werfen instancezu com.foo.MyClass? vorausgesetzt , com.foo.MyClass ist nur eine Zeichenfolge
Sanket9394
14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
scibuff
quelle
15
Es ist erwähnenswert, dass dies nicht funktioniert, wenn die Klasse keinen parameterlosen Konstruktor hat (und andere Konstruktoren hat) oder wenn auf den parameterlosen Konstruktor nicht zugegriffen werden kann.
Dawood ibn Kareem
3

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

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

Dies führt dazu, dass die Klasse A initialisiert wird.

Chandra Sekhar
quelle
Funktioniert bei mir nicht, auch wenn der Paketname vorangestellt ist. :(
trusktr
3

Um es einfacher zu machen, den vollständig qualifizierten Namen einer Klasse zu erhalten, um eine Instanz mit zu erstellen Class.forName(...), könnte man die Class.getName()Methode verwenden. Etwas wie:

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;
    }
}

Dann können Sie das Objekt, das Sie erhalten, in die Klasse umwandeln, an die Sie übergeben makeObject(...):

Data d = (Data) objectMaker.makeObject(Data.class);
Roberto
quelle
1
Kannst du nicht einfach clazz.newInstance()statt der getNamedann fromName?
user276648
1

Verwenden Sie Java Reflection

Erstellen neuer Objekte Es gibt kein Äquivalent zum Methodenaufruf für Konstruktoren, da das Aufrufen eines Konstruktors dem Erstellen eines neuen Objekts entspricht (genauer gesagt umfasst das Erstellen eines neuen Objekts sowohl die Speicherzuweisung als auch die Objektkonstruktion). Das nächste Äquivalent zum vorherigen Beispiel lautet also:

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);
         }
      }
   }

Hiermit wird ein Konstruktor gefunden, der die angegebenen Parametertypen verarbeitet und aufruft, um eine neue Instanz des Objekts zu erstellen. Der Wert dieses Ansatzes besteht darin, dass er rein dynamisch ist und die Konstruktorsuche und der Aufruf zur Ausführungszeit und nicht zur Kompilierungszeit erfolgen.

kornero
quelle
1

Class.forName ("ClassName") löst Ihren Zweck.

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

so etwas sollte funktionieren ...

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

Die newInstance()direkte Verwendung ist ab Java 8 veraltet. Sie müssen sie Class.getDeclaredConstructor(...).newInstance(...)mit den entsprechenden Ausnahmen verwenden.

Mel
quelle