Java:访问具有types参数的私有构造函数
这是关于java私有构造函数的这个问题的后续。
假设我有以下class级:
class Foo<T> { private T arg; private Foo(T t) { // private! this.arg = t; } @Override public String toString() { return "My argument is: " + arg; } }
我将如何使用reflection来构造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); } }
你需要得到这个类,find构造函数,该构造函数接受T的下界(这里是Object)的一个参数,强制构造函数可访问(使用setAccessible
方法),最后用所需的参数调用它。
确保在获取构造函数时使用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);
那么万一私人构造函数没有采取任何参数,那么我们在创build新实例的时候抓取问题,在这种情况下,在setAccessible之后,我们不能创build对象。 即使construct.newInstance(null);
不会为无参数构造函数创build对象。
我们可以使用reflection来创build下面的代码的对象:
public class Singleton { private static Singleton instance = new Singleton(); /* private constructor */ private Singleton() {} public static Singleton getDefaultInstance() { return instance; } }
是的,我们可以创build上述课程的对象。
// 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:我的博客“渴望初始化”和“反思的单身人士违规”: http : //sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/
正如@ArtB所说,你可以使用dp4j.com , 如果你知道你想在编译时使用的构造函数 。 在项目主页上有一个例子,访问一个Singleton构造函数。
而不是JUnit的@Test注释用@Reflect注入Reflection的方法:
public class Example { @com.dp4j.Reflect public static void main(final String[] args){ Foo<String> foo = new Foo("hello"); System.out.println(foo); } }
要查看reflection生成的代码,请在此答案中使用-Averbose = true参数。
如果Junittesting类(在testing文件夹中)与实际类具有相同的包名,那么从Junittesting用例中,我们可以调用所有的私有方法来testing,而不需要像dp4j那样的额外的库。
有一个JUnit库( dp4j ),可以自动插入访问私有方法的代码。 这可能是有用的。