【发布时间】:2011-08-30 23:25:40
【问题描述】:
有没有办法在给定类名(动态)的情况下创建特定类的实例并将参数传递给它的构造函数。
类似:
Object object = createInstance("mypackage.MyClass","MyAttributeValue");
其中"MyAttributeValue" 是MyClass 的构造函数的参数。
【问题讨论】:
标签: java reflection instantiation
有没有办法在给定类名(动态)的情况下创建特定类的实例并将参数传递给它的构造函数。
类似:
Object object = createInstance("mypackage.MyClass","MyAttributeValue");
其中"MyAttributeValue" 是MyClass 的构造函数的参数。
【问题讨论】:
标签: java reflection instantiation
是的,类似:
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")。
【讨论】:
newInstance() 是一个可变参数方法(就像GetConstructor()),不需要显式创建Object-array。
Object[] 参数时它会变得很棘手,我更喜欢在这种情况下显式创建数组。
您可以使用Class.forName() 获取所需类的Class 对象。
然后使用getConstructor() 找到所需的Constructor 对象。
最后,在该对象上调用 newInstance() 以获取您的新实例。
Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");
【讨论】:
你可以使用反射
return Class.forName(className).getConstructor(String.class).newInstance(arg);
【讨论】:
Class.forName(className).getConstructor().newInstance(); ;)
如果类只有一个空构造函数(如Activity或Fragment等,android类):
Class<?> myClass = Class.forName("com.example.MyClass");
Constructor<?> constructor = myClass.getConstructors()[0];
【讨论】:
Constructor<?> ctor = clazz.getConstructor(String.class) 似乎对我不起作用。
当使用(即)getConstructor(String.lang) 时,必须将构造函数声明为 public。
否则会抛出 NoSuchMethodException。
如果您想访问 非公共构造函数,则必须改用(即)getDeclaredConstructor(String.lang)。
【讨论】:
使用 Class<?> 并传递构造函数参数在 Java 中创建对象的非常简单的方法:
案例 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" });
这里的 Base 类应该是这样的:
public class Base {
public Base(String a, String b, String c){
// This constructor need to be created in this case.
}
}
注意:- 不要忘记处理代码中需要处理的各种异常。
【讨论】:
如果有人正在寻找一种方法来创建一个类的实例,尽管该类遵循单例模式,这里有一种方法。
// 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();
这仅适用于使用私有构造函数实现单例模式的类。
【讨论】:
另一个有用的答案。 How do I use 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);
【讨论】:
您还可以在创建的对象中调用方法。
您可以通过调用第一个构造器来立即创建对象,然后在创建的对象中调用第一个方法。
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);
【讨论】:
String作为参数?更改构造函数顺序时变得有点混乱
getConstructor(ClassName.class) 更好。即使类中构造函数的顺序发生变化,也无需手动查找位置