4 min read

Constructor Reflection in Java

Constructor reflection allows you to invoke a constructor and create an instance of that class.
Constructor Reflection in Java

Constructor Reflection

Constructor reflection is a runtime feature that allows you to dynamically invoke constructors and create instances of a class at runtime. You can also find what modifiers, parameters, and checked exceptions are on the constructor signature. Constructor reflection is done using the java.reflect.Constructor class. Instances of this class can be obtained from java.lang.Class. The following class will be used for the examples in this article.

package press.bytesize;

public class User {

    private User(final int id, final String fullName) {
    }

    public User(final User user) throws CantCopyException {
    }

    public User() {
    }
}

Obtaining java.reflect.Constructor Instances

Once a java.lang.Class instance is obtained for the class you are wanting to use reflection on, you can obtain a java.reflect.Constructor instance a few different ways depending on your use case. Unlike java.lang.Classjava.reflect.Constructor instances are not singletons.

java.reflect.Constructor instance for each of the constructors above on the User class can be obtained using the getDeclaredConstructor() method. If a constructor doesn't exist, the getDeclaredConstructor() will throw a NoSuchMethodException. When working with constructors, you must specify the parameter types for that constructor.

final Constructor<User> privateConstructor = 
        User.class.getDeclaredConstructor(int.class, String.class);
final Constructor<User> copyConstructor = 
        User.class.getDeclaredConstructor(User.class);
final Constructor<User> defaultConstructor = 
        User.class.getDeclaredConstructor();

All constructors in the User class can be obtained using the getDeclaredConstructors() method.

final Constructor<?>[] constructors = 
        User.class.getDeclaredConstructors();

If you are working with public constructors, you can use getConstructor() and getConstructors() instead. These will only return a constructor if it is public and will throw a NoSuchMethodException if the constructor doesn't exist or if it isn't public.

java.reflect.Constructor Class

Constructors have modifiers, a return type, a name, parameters, and exceptions. You can print out the method signature using the toGenericString() method.

final Constructor<User> copyConstructor = 
        User.class.getDeclaredConstructor(User.class);

System.out.println(copyConstructor.toGenericString());

This will print the following:

public press.bytesize.User(press.bytesize.User) throws CantCopyException

Constructor Accessibility

To invoke a constructor using reflection, constructors must either be marked as public or be accessible before you can invoke them. This is done using the setAccessible() method. If a constructor cannot be accessed due to the lack of permission defined by the SecurityManager, a SecurityException will be thrown. These permissions are different from the access modifier.

final Constructor<Reflection> privateConstructor =
        User.class.getDeclaredConstructor(int.class, String.class);
privateConstructor.setAccessible(true);

Java 9 introduced the trySetAccessible() method. This will return true if you have permission to make it accessible; otherwise, it will return false.

final Constructor<Reflection> privateConstructor =
        User.class.getDeclaredConstructor(int.class, String.class);

if (privateConstructor.trySetAccessible()) {
    // Do something...
} else {
    // You do not have permissions...
}

Creating Instances

An instance of a class can be created from a specific constructor using the newInstance() method. This takes a varargs parameter for each argument you are wanting to pass to the constructor. For constructors not marked as public, you must make the java.reflect.Constructor instance accessible before invoking it.

final Constructor<Reflection> privateConstructor =
        User.class.getDeclaredConstructor(int.class, String.class);
privateConstructor.setAccessible(true);

final User user = privateConstructor.newInstance(10, "fullName");

This creates an instance of the User class using the private constructor, passing the parameters 10 and "fullName" to it.

Constructor Parameters

Parameters can have a final modifier, a type, and a name. Each of these is represented in the java.lang.Parameter class. You can get an array of each of the parameters in a constructor using the getParameters() method.

final Constructor<User> defaultConstructor = 
        User.class.getDeclaredConstructor();
final Parameter[] parameters = defaultConstructor.getParameters();

You can also get a count of the number of parameters a constructor has using the getParameterCount() method.

final Constructor<User> defaultConstructor =
        User.class.getDeclaredConstructor();
final int parameterCount = defaultConstructor.getParameterCount();

Constructor Exceptions

You can get an array of the exceptions defined in the throws clause of the constructor signature using getExceptionTypes(). This returns an array of java.lang.Classes. If there isn't any exception defined on the throws clause, this returns an empty array.

final Constructor<User> copyConstructor = 
        User.class.getDeclaredConstructor(User.class);
final Class<?>[] exceptionTypes = copyConstructor.getExceptionTypes();

Constructor Modifiers

You can find out if a constructor is marked with a specific modifier using the getModifiers() method. This returns an int. You can then use the java.lang.Modifier class to see if a constructor has a specific modifier.

final Constructor<User> defaultConstructor =
        User.class.getDeclaredConstructor();

System.out.println(Modifier.isPublic(id.getModifiers())); // true
System.out.println(Modifier.isPrivate(id.getModifiers())); // false

Java 20 introduced the accessFlags() method. This returns a java.util.Set of java.lang.reflect.AccessFlags. You can then check to see if the Set contains an AccessFlag.

final Constructor defaultConstructor = 
        User.class.getDeclaredConstructor("id");
final Set<AccessFlag> flags = defaultConstructor.accessFlags();

System.out.println(flags.contains(AccessFlag.PUBLIC)); // true
System.out.println(flags.contains(AccessFlag.PRIVATE)); // false

Conclusion

Constructor reflection allows you to get information such as the modifier, parameters, and exceptions. You can invoke a constructor using reflection regardless of the access modifier.