webentwicklung-frage-antwort-db.com.de

Erstellen einer Instanz mit dem Klassennamen und dem aufrufenden Konstruktor

Gibt es eine Möglichkeit, eine Instanz einer bestimmten Klasse anhand des Klassennamens (dynamisch) zu erstellen und Parameter an ihren Konstruktor zu übergeben?.

So etwas wie:

Object object = createInstance("mypackage.MyClass","MyAttributeValue");

Wobei "MyAttributeValue" ein Argument für den Konstruktor von MyClass ist.

290

Ja, so etwas wie:

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });

Das funktioniert natürlich nur für einen einzelnen String-Parameter, aber Sie können ihn ziemlich einfach ändern.

Beachten Sie, dass der Klassenname ein vollständig qualifizierter Name sein muss, d. H. Einschließlich des Namespaces. Für verschachtelte Klassen müssen Sie einen Dollar verwenden (da dies vom Compiler verwendet wird). Zum Beispiel:

package foo;

public class Outer
{
    public static class Nested {}
}

Um das Objekt Class dafür zu erhalten, benötigen Sie Class.forName("foo.Outer$Nested").

471
Jon Skeet

Sie können Class.forName() verwenden, um ein Class Objekt der gewünschten Klasse abzurufen.

Verwenden Sie dann getConstructor() , um das gewünschte Constructor Objekt zu finden.

Rufen Sie abschließend newInstance() für dieses Objekt auf, um Ihre neue Instanz abzurufen.

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
91
Joachim Sauer

Sie können Reflexionen verwenden

return Class.forName(className).getConstructor(String.class).newInstance(arg);
79
Peter Lawrey

Wenn die Klasse nur einen leeren Konstruktor hat (wie Aktivität oder Fragment usw., Android Klassen):

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];
12
tier777

bei Verwendung von (d. h.) getConstructor(String.lang) muss der Konstruktor als public deklariert werden. Andernfalls wird ein NoSuchMethodException geworfen.

wenn Sie auf einen nicht öffentlichen Konstruktor zugreifen möchten, müssen Sie stattdessen (d. h.) getDeclaredConstructor(String.lang) verwenden.

8
4
Alan Escreet

Sehr einfache Methode zum Erstellen eines Objekts in Java mit Class<?> mit übergebenen Konstruktorargumenten:

Fall 1: - Hier ist ein kleiner Code in dieser Main Klasse:

import Java.lang.reflect.Constructor;
import Java.lang.reflect.InvocationTargetException;

public class Main {

    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        // Get class name as string.
        String myClassName = Base.class.getName();
        // Create class of type Base.
        Class<?> myClass = Class.forName(myClassName);
        // Create constructor call with argument types.
        Constructor<?> ctr = myClass.getConstructor(String.class);
        // Finally create object of type Base and pass data to constructor.
        String arg1 = "My User Data";
        Object object = ctr.newInstance(new Object[] { arg1 });
        // Type-cast and access the data from class Base.
        Base base = (Base)object;
        System.out.println(base.data);
    }

}

Und hier ist die Base Klassenstruktur:

public class Base {

    public String data = null;

    public Base() 
    {
        data = "default";
        System.out.println("Base()");
    }

    public Base(String arg1) {
        data = arg1;
        System.out.println("Base("+arg1+")");
    }

}

Fall 2: - Sie können den Konstruktor mit mehreren Argumenten auf ähnliche Weise codieren und den Konstruktor kopieren. Wenn Sie beispielsweise 3 Argumente als Parameter an den Konstruktor Base übergeben, muss der Konstruktor in der Klasse erstellt und der Code wie folgt geändert werden:

Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" }); 

Und hier sollte die Basisklasse irgendwie so aussehen:

public class Base {

    public Base(String a, String b, String c){
        // This constructor need to be created in this case.
    }   
}

Hinweis: - Vergessen Sie nicht, die verschiedenen Ausnahmen zu behandeln, die im Code behandelt werden müssen.

4
Rahul Raina

Wenn jemand nach einer Möglichkeit sucht, eine Instanz einer Klasse zu erstellen, obwohl die Klasse dem Singleton-Muster folgt, finden Sie hier eine Möglichkeit, dies zu tun.

// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");

// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();

// Since it is private, make it accessible.
cons.setAccessible(true);

// Create new object. 
Object obj = cons.newInstance();

Dies funktioniert nur für Klassen, die Singleton-Muster mit einem privaten Konstruktor implementieren.

1
Omer

Sie können auch Methoden innerhalb des erstellten Objekts aufrufen.

Sie können ein Objekt sofort erstellen, indem Sie den ersten Constractor aufrufen und dann die erste Methode im erstellten Objekt aufrufen.

    Class<?> c = Class.forName("mypackage.MyClass");
    Constructor<?> ctor = c.getConstructors()[0];
    Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
    c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);
1
Hatem Badawi

Eine weitere hilfreiche Antwort. Wie verwende ich getConstructor (params) .newInstance (args)?

return Class.forName(**complete classname**)
    .getConstructor(**here pass parameters passed in constructor**)
    .newInstance(**here pass arguments**);

In meinem Fall verwendet der Konstruktor meiner Klasse Webdriver als Parameter und wird daher im folgenden Code verwendet:

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
0
user3181500