Создание экземпляра с использованием имени класса и вызывающего конструктора - PullRequest
288 голосов
/ 23 мая 2011

Есть ли способ создать экземпляр определенного класса с заданным именем класса (динамический) и передать параметры его конструктору.

Что-то вроде:

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

Где "MyAttributeValue" - аргумент для конструктора MyClass.

Ответы [ 10 ]

469 голосов
/ 23 мая 2011

Да, что-то вроде:

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

Конечно, это будет работать только для одного строкового параметра, но вы можете довольно легко его изменить.

Обратите внимание, что имя класса должно быть полностью квалифицированным, т.е. включать пространство имен. Для вложенных классов вам нужно использовать доллар (так как это то, что использует компилятор). Например:

package foo;

public class Outer
{
    public static class Nested {}
}

Чтобы получить для этого Class объект, вам понадобится Class.forName("foo.Outer$Nested").

90 голосов
/ 23 мая 2011

Вы можете использовать Class.forName(), чтобы получить Class объект нужного класса.

Затем используйте getConstructor()чтобы найти нужный Constructor объект.

Наконец, вызовите newInstance() для этого объекта, чтобы получить новый экземпляр.

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
79 голосов
/ 23 мая 2011

Вы можете использовать отражения

return Class.forName(className).getConstructor(String.class).newInstance(arg);
12 голосов
/ 12 сентября 2014

Если в классе есть только один пустой конструктор (например, Activity или Fragment и т. Д., Классы Android):

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];
8 голосов
/ 02 октября 2014

при использовании (т.е.) getConstructor(String.lang) конструктор должен быть объявлен открытым. В противном случае выбрасывается NoSuchMethodException.

если вы хотите получить доступ к непубличному конструктору , вы должны использовать вместо этого (т.е.) getDeclaredConstructor(String.lang).

4 голосов
/ 17 августа 2017

Очень простой способ создания объекта в Java с использованием Class<?> с передачей аргументов конструктора:

Случай 1: - Вот небольшой код в этом 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);
    }

}

И, вот структура класса Base:

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

}

Случай 2: - Вы можете аналогичным образом кодировать конструктор с несколькими аргументами и конструктор копирования. Например, передача 3 аргументов в качестве параметра конструктору Base потребует создания конструктора в классе и изменения кода выше как:

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

А вот базовый класс должен выглядеть так:

public class Base {

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

Примечание: - Не забудьте обработать различные исключения, которые необходимо обработать в коде.

4 голосов
/ 23 мая 2011

Вы хотите использовать java.lang.reflect.Constructor.newInstance (Object ...)

1 голос
/ 11 сентября 2017

Если кто-то ищет способ создания экземпляра класса, несмотря на то, что класс следует шаблону Singleton, вот способ сделать это.

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

Это работает только для классов, которые реализуют singletonшаблон с использованием частного конструктора.

1 голос
/ 14 декабря 2015

Вы также можете вызывать методы внутри созданного объекта.

Вы можете мгновенно создать объект, вызвав первый конструктор и затем вызвав первый метод в созданном объекте.

    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);
0 голосов
/ 05 января 2017

Еще один полезный ответ. Как использовать getConstructor (params) .newInstance (args)?

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

В моем случае конструктор моего класса принимает Webdriver в качестве параметра, поэтому используется следующий код:

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