这是关于java私有构造函数问题的后续问题。
假设我有以下类:
class Foo<T>
{
private T arg;
private Foo(T t) {
// private!
this.arg = t;
}
@Override
public String toString() {
return "My argument is: " + arg;
}
}
如何使用反射构造new Foo("hello")
?
根据jtahlborn的回答,以下工作:
public class Example {
public static void main(final String[] args) throws Exception {
Constructor<Foo> constructor;
constructor = Foo.class.getDeclaredConstructor(Object.class);
constructor.setAccessible(true);
Foo<String> foo = constructor.newInstance("arg1");
System.out.println(foo);
}
}
确保在获取构造函数时使用getDeclaredConstructors
,并将其可访问性设置为true,因为它是私有的。
这样应该可以工作。
Constructor<Foo> constructor= (Constructor<Foo>) Foo.class.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Foo obj = constructor.newInstance("foo");
System.out.println(obj);
如果你想使用getDeclaredConstructor,传递Object.class作为参数,它会转换成一个泛型t。
Class fooClazz = Class.forName("path.to.package.Foo");
Constructor<Foo> constructor = fooClazz.getDeclaredConstructor(Object.class);
constructor.setAccessible(true);
Foo obj = constructor.newInstance("foo");
System.out.println(obj);
你需要获得类,找到构造函数,它接受一个具有T下界的参数(在本例中是Object),强制构造函数是可访问的(使用setAccessible
方法),最后用所需的参数调用它
如果私有构造函数没有接受任何参数,那么我们在创建新实例时就会遇到问题,在这种情况下,setAccessible为true后我们就不能创建对象了。即使construct.newInstance(null);
也不会为无参数构造函数创建对象。
可以使用反射创建如下代码的对象:
public class Singleton {
private static Singleton instance = new Singleton();
/* private constructor */
private Singleton() {}
public static Singleton getDefaultInstance() {
return instance;
}
}
是的,我们可以创建上面类的对象。
// reflection concept to get constructor of a Singleton class.
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
// change the accessibility of constructor for outside a class object creation.
constructor.setAccessible(true);
// creates object of a class as constructor is accessible now.
Singleton secondOb = constructor.newInstance();
// close the accessibility of a constructor.
constructor.setAccessible(false);
你可以参考:示例2:"Eager Initialization"one_answers"Singleton Violation by reflection"在我的博客:http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/
正如@ArtB所说,如果您知道要在编译时使用的构造函数,则可以使用dp4j.com 。在项目主页上有一个这样的例子,访问一个Singleton构造函数。
用@Reflect来代替JUnit的@Test注释要注入反射的方法:
public class Example {
@com.dp4j.Reflect
public static void main(final String[] args){
Foo<String> foo = new Foo("hello");
System.out.println(foo);
}
}
要查看反射生成的代码,请使用-Averbose=true参数。
如果Junit测试类(在测试文件夹中)具有与实际类相同的包名,那么从Junit测试用例中,我们可以调用所有私有方法进行测试,而不需要任何额外的库,如dp4j。
有一个用于JUnit (dp4j)的库,它自动插入用于访问私有方法的代码。这也许有用。
起初我使用反射获得NoSuchMethodException
使用:
Constructor<TestClass> constructor= (Constructor<TestClass>) TestClass.class.getDeclaredConstructors()[0];