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.


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

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

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.


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

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.



0
String str = (String)Class.forName("java.lang.String").newInstance();

0

so etwas sollte funktionieren ...

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

0

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.