Crear una instancia usando el nombre de la clase y llamar al constructor


Hay una manera de crear una instancia de una clase particular dado el nombre de la clase (dinámico) y pasar parámetros a su constructor.

Algo como:

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

Donde "MyAttributeValue" es un argumento para el constructor de MyClass.

Author: Bathsheba, 2011-05-23

10 answers

Sí, algo así como:

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

Eso solo funcionará para un solo parámetro de cadena, por supuesto, pero puede modificarlo bastante fácilmente.

Tenga en cuenta que el nombre de la clase tiene que ser totalmente cualificado, es decir, incluyendo el espacio de nombres. Para las clases anidadas, necesita usar un dólar (ya que eso es lo que usa el compilador). Por ejemplo:

package foo;

public class Outer
{
    public static class Nested {}
}

Para obtener el objeto Class para eso, necesitarías Class.forName("foo.Outer$Nested").

 432
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-11 17:51:30

Puede utilizar Class.forName() para obtener una Class objeto de la clase deseada.

Luego use getConstructor() para encontrar el deseado Constructor objeto.

Finalmente, llame newInstance() en ese objeto para obtener su nueva instancia.

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
 82
Author: Joachim Sauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-23 08:23:12

Puedes usar reflexiones

return Class.forName(className).getConstructor(String.class).newInstance(arg);
 71
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-23 08:24:03

Si la clase solo tiene un constructor vacío (como Activity o Fragment, etc., clases de Android):

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];
 12
Author: tier777,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-11 22:09:21

Cuando se usa (es decir,) getConstructor(String.lang) el constructor tiene que ser declarado público. De lo contrario se lanza un NoSuchMethodException.

Si quieres acceder a un constructor no público tienes que usar en su lugar (es decir) getDeclaredConstructor(String.lang).

 7
Author: matthiasboesinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-02 11:12:49
 3
Author: Alan Escreet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-23 08:24:31

Forma muy sencilla de crear un objeto en Java usando Class<?> con el(los) argumento (s) del constructor pasando:

Caso 1: - Aquí, hay un pequeño código en esta clase Main:

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

}

Y, aquí está la Base estructura de clases:

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

}

Caso 2: - Usted, puede codificar de manera similar para constructor con múltiples argumentos y constructor de copia. Por ejemplo, pasar 3 argumentos como parámetro al constructor Base necesitará que el constructor se cree en clase y un cambio de código en arriba como:

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

Y aquí la clase Base debería verse de alguna manera como:

public class Base {

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

Nota:- No se olvide de manejar las diversas excepciones que deben ser manejadas en el código.

 2
Author: Rahul Raina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-17 08:08:40

También puede invocar métodos dentro del objeto creado.

Puede crear objeto instantáneo invocando el primer constractor y luego invocar el primer método en el objeto creado.

    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
Author: Hatem Badawi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-13 22:47:33

Si alguien está buscando una manera de crear una instancia de una clase a pesar de que la clase sigue el patrón Singleton, aquí hay una manera de hacerlo.

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

Esto solo funciona para clases que implementan patrón singleton usando un constructor privado.

 1
Author: Omer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-11 00:55:10

Otra respuesta útil. Cómo uso getConstructor(parámetros).newInstance (args)?

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

En mi caso, el constructor de mi clase toma Webdriver como parámetro, por lo que se usa debajo del código:

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
 -1
Author: user3181500,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-11 21:32:17