Java:使用类型参数访问私有构造函数
Posted
技术标签:
【中文标题】Java:使用类型参数访问私有构造函数【英文标题】:Java: accessing private constructor with type parameters 【发布时间】:2011-08-03 12:51:48 【问题描述】:这是this question about java private constructors 的后续。
假设我有以下课程:
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's answer,以下工作:
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);
【问题讨论】:
它不起作用:( java.lang.NoSuchMethodException: my.package.path.Foo.起初我使用反射得到 NoSuchMethodException。
使用这个:
Constructor<TestClass> constructor= (Constructor<TestClass>) TestClass.class.getDeclaredConstructors()[0];
【讨论】:
【参考方案2】:如果 Junit 测试类(在测试文件夹中)与实际类具有相同的包名,那么从 Junit 测试用例中,我们可以调用所有私有方法进行测试,而无需任何额外的库,如 dp4j。
【讨论】:
如果你的类在 src/main/java 文件夹和包中:com.temp(这个类有私有构造函数)假设你的测试类在 src/test/java 文件夹和包中com.temp。在这种情况下,您无法使用测试类访问实际类的私有构造函数。您必须通过 dp4j 库或使用您自己的反射代码来使用反射。【参考方案3】:如果私有构造函数不带任何参数,那么我们在创建新实例时会获取问题,在这种情况下,在 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”和“Singleton Violation by reflection”:http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/
【讨论】:
【参考方案4】:正如@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 参数,如 this answer。
【讨论】:
【参考方案5】:确保在获取构造函数时使用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);
【讨论】:
我不知道为什么,但我收到一个异常,说我的构造函数不存在(它确实存在)。有任何想法吗? More Info【参考方案6】:有一个 JUnit 库 (dp4j) 可以自动插入代码以访问私有方法。这可能有用。
【讨论】:
【参考方案7】:您需要获取类,找到接受单个参数的构造函数,其下限为 T(在本例中为 Object),强制构造函数可访问(使用 setAccessible
方法),最后调用它与所需的参数。
【讨论】:
这篇文章可能会有所帮助:dunwood.blogspot.com/2004/05/…以上是关于Java:使用类型参数访问私有构造函数的主要内容,如果未能解决你的问题,请参考以下文章