Java: accessing private constructor with type parameters

59,135

Solution 1

you would need to get the class, find the constructor which takes a single argument with the lower bound of T (in this case Object), force the constructor to be accessible (using the setAccessible method), and finally invoke it with the desired argument.

Solution 2

Make sure you use getDeclaredConstructors when getting the constructor and set its accessibility to true since its private.

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.

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

Solution 3

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. Even 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/

Solution 4

As @ArtB said you could use dp4j.com, if you know the constructor you want to use at compile-time. On the project homepage there's an example of just that, accessing a Singleton constructor.

Instead of JUnit's @Test annotate the method in which to inject the Reflection with @Reflect:

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.

Solution 5

If Junit Test Class (in Test Folder) has the same package name as of Actual Class, then from Junit Test case, we can call all private methods to test, without any additional library like dp4j.

Share:
59,135

Related videos on Youtube

dsg
Author by

dsg

Updated on July 05, 2022

Comments

  • dsg
    dsg over 1 year

    This is a followup to this question about java private constructors.

    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?

    ANSWER

    Based on jtahlborn's answer, the following works:

    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);
        }   
    }
    
    • Dima R.
      Dima R. about 8 years
      It does not work :( java.lang.NoSuchMethodException: my.package.path.Foo.<init>(java.lang.Object) at java.lang.Class.getConstructor0(Class.java:2892) at java.lang.Class.getDeclaredConstructor(Class.java:2058) at ProductCatalogAgentTest.testConnect(ProductCatalogAgentTest.‌​java:461) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  • user3137901
    user3137901 over 12 years
    This article might help: dunwood.blogspot.com/2004/05/…
  • Sanjay Madnani
    Sanjay Madnani over 7 years
    If your Class is in src/main/java folder and in package: com.temp (this class has private constructor) and let's say your test class is in src/test/java folder and in package com.temp. In this cases you cannot access private constructor of actual class with test class. You must have to use reflection either via dp4j Library or by using your own reflection code.

Related