使用类名创建实例并调用构造函数

The*_*mer 299 java reflection instantiation

有没有办法在给定类名(动态)的情况下创建特定类的实例,并将参数传递给其构造函数.

就像是:

Object object = createInstance("mypackage.MyClass","MyAttributeValue");
Run Code Online (Sandbox Code Playgroud)

哪个"MyAttributeValue"是构造函数的参数MyClass.

Jon*_*eet 482

是的,像是这样的:

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

当然,这只适用于单个字符串参数,但您可以非常轻松地修改它.

请注意,类名必须是完全限定的类名,即包含名称空间.对于嵌套类,您需要使用一美元(就像编译器使用的那样).例如:

package foo;

public class Outer
{
    public static class Nested {}
}
Run Code Online (Sandbox Code Playgroud)

要获得该Class对象,您需要Class.forName("foo.Outer$Nested").

  • @Joachim:我知道它是varargs,但是当你有一个`Object []`参数时它会变得棘手,我更喜欢在这种情况下显式创建数组. (18认同)
  • `newInstance()`是一个varargs方法(就像`GetConstructor()`),不需要显式的`Object`-array创建. (5认同)
  • @JonSkeet 我明白你来自哪里,但是它不是那么简单 - 我确实看过文档但很困惑,但如果我测试它并且它有效 - 好的那么它有效 - 但如果它没有工作然后我一直不确定问题是否是由于缺乏配置或我的原因造成的 - 通常在提出如此简单的问题时,人们会抛出真正有帮助的有用花絮。这就是为什么一个简单的“是的,会起作用 - 如果你这样做”或“不,没有办法”,真的有帮助。但我现在的理解是没有办法 (3认同)
  • clazz.getConstructor(String.class); 为什么在这里使用String.class? (2认同)
  • @Neutralizer:是的,但我回答的问题是它不需要动态. (2认同)

Joa*_*uer 93

您可以使用Class.forName()获取Class所需类的对象.

然后getConstructor()用来找到所需的Constructor对象.

最后,调用newInstance()该对象来获取新实例.

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
Run Code Online (Sandbox Code Playgroud)


Pet*_*rey 80

你可以使用反射

return Class.forName(className).getConstructor(String.class).newInstance(arg);
Run Code Online (Sandbox Code Playgroud)

  • @VijayKumar我认为你的意思是`Class.forName(className).getConstructor().newInstance();`;) (20认同)
  • 如果使用默认构造函数,则删除String.class参数值,例如返回Class.forName(className).getConstructor().newInstance(arg); (3认同)

小智 13

如果类只有一个空构造函数(如Activity或Fragment等,android类):

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];
Run Code Online (Sandbox Code Playgroud)

  • 这就是帮助我的原因。`Constructor&lt;?&gt; ctor = clazz.getConstructor(String.class)` 似乎对我不起作用。 (2认同)

mat*_*ger 8

当使用(即)时getConstructor(String.lang),必须将构造函数声明为public.否则NoSuchMethodException抛出一个.

如果要访问非公共构造函数,则必须使用(即)getDeclaredConstructor(String.lang).


小智 6

如果有人正在寻找一种方法来创建类的实例,尽管该类遵循单例模式,那么这里有一种方法。

// 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();
Run Code Online (Sandbox Code Playgroud)

这只适用于使用私有构造函数实现单例模式的类。


use*_*500 5

另一个有用的答案。如何使用 getConstructor(params).newInstance(args)?

return Class.forName(**complete classname**)
    .getConstructor(**here pass parameters passed in constructor**)
    .newInstance(**here pass arguments**);
Run Code Online (Sandbox Code Playgroud)

就我而言,我的类的构造函数采用 Webdriver 作为参数,因此使用以下代码:

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
Run Code Online (Sandbox Code Playgroud)