简体   繁体   English

Java:使用类型参数访问私有构造函数

[英]Java: accessing private constructor with type parameters

This is a followup to this question about java private constructors . 这是关于java私有构造函数的这个问题的后续内容

Suppose I have the following class: 假设我有以下课程:

class Foo<T>
{
    private T arg;
    private Foo(T t) {
        // private!
        this.arg = t;
    }   

    @Override
    public String toString() {
        return "My argument is: " + arg;
    }   
}

How would I construct a new Foo("hello") using reflection? 我如何使用反射构造一个new Foo("hello")

ANSWER 回答

Based on jtahlborn's answer , the following works: 根据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);
    }   
}

Make sure you use getDeclaredConstructors when getting the constructor and set its accessibility to true since its private. 确保在获取构造函数时使用getDeclaredConstructors ,并将其可访问性设置为true,因为它是私有的。

Something like this should work. 这样的事情应该有效。

Constructor<Foo> constructor= (Constructor<Foo>) Foo.class.getDeclaredConstructors()[0];
constructor.setAccessible(true); 
Foo obj = constructor.newInstance("foo"); 
System.out.println(obj);

Update 更新

If you want to make use of getDeclaredConstructor, pass Object.class as an argument which translates to a generic T. 如果要使用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方法),最后使用所需的参数调用它。

Well in case if private constructor does not take any argument then we fetch problem while creating new instance, in this case after setAccessible true we can't create object. 好吧,如果私有构造函数不接受任何参数,那么我们在创建新实例时获取问题,在这种情况下,在setAccessible为true后我们无法创建对象。 Even construct.newInstance(null); 甚至construct.newInstance(null); won't create object for no argument constructor. 不会为没有参数构造函数创建对象。

can we create object of below code using reflection: 我们可以使用反射创建下面代码的对象:

public class Singleton {

    private static Singleton instance = new Singleton();

    /* private constructor */
    private Singleton() {}

    public static Singleton getDefaultInstance() {
        return instance;
    }
}

Yes we can create the object of above class. 是的,我们可以创建上面的类的对象。

// 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);

You can Refer: Example 2: "Eager Initialization" and "Singleton Violation by reflection" of my blog: http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/ 您可以参考:示例2:我的博客中的“Eager Initialization”和“Singleton Violation by reflection”: http//sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/

As @ArtB said you could use dp4j.com , if you know the constructor you want to use at compile-time . 正如@ArtB所说,你可以使用dp4j.com如果你知道你想在编译时使用的构造函数 On the project homepage there's an example of just that, accessing a Singleton constructor. 在项目主页上有一个例子,访问Singleton构造函数。

Instead of JUnit's @Test annotate the method in which to inject the Reflection with @Reflect: 而不是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);
    }   
}

To see the reflection generated code use -Averbose=true argument as in this answer . 要查看反射生成的代码,请使用-Averbose = true参数, 如此答案中所示

如果Junit测试类(在测试文件夹中)具有与实际类相同的包名,那么从Junit测试用例中,我们可以调用所有私有方法进行测试,而不需要任何额外的库,如dp4j。

There is a library for JUnit ( dp4j ) that automatically inserts code for accessing private methods. JUnit( dp4j )有一个库,可以自动插入访问私有方法的代码。 That may be of use. 这可能有用。

At first I was getting NoSuchMethodException using reflection. 起初我使用反射得到NoSuchMethodException。

Use this: 用这个:

Constructor<TestClass> constructor= (Constructor<TestClass>) TestClass.class.getDeclaredConstructors()[0];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM