Previous in the Series
Current Tutorial
Invoking Constructors
Next in the Series

Previous in the Series: Invoking Methods

Next in the Series: Working with Arrays

Invoking Constructors

A Constructor object lets you get more information on the corresponding constructor: its modifiers, the types and names of its parameters, and enables you to invoke to create instance of objects, passing the arguments you need. This section also covers how you can discover constructors in a class.

 

Locating Constructors

There are two categories of methods provided in Class for accessing constructors.

  1. First, you can look for a specific constructor. These methods suppose you have the type of its parameter.
  2. Second, you can either look for all the constructors that are declared in this class. In that case, you will get all the constructors: public, protected, default (package) access, and private. Or you can look for the public constructors only.

Note that constructors are not inherited, so you do not have any equivalent to the methods you saw on fields or methods, to locate elements on inherited classes.

Class API Array of constructors? Private constructors?
getDeclaredConstructor(Class...) no yes
getConstructor(Class...) no no
getDeclaredConstructors() yes yes
getConstructors() yes no

A constructor declaration includes the name, modifiers, parameters, and list of throwable exceptions. The java.lang.reflect.Constructor class provides a way to obtain this information.

Let us see this method in action. The following code queries the constructors of the String class.

The following code prints the 19 constructors you have in this class in the JDK 23. Note that not all of them are public.

Class<?> c = String.class;
Constructor<?>[] constructors = c.getDeclaredConstructors();
System.out.println("# constructors = " + constructors.length);
for (Constructor<?> constructor : constructors) {
    System.out.println("constructor = " + constructor);
}

Running this code produces the following.

# constructors = 19
constructor = public java.lang.String(java.lang.StringBuilder)
constructor = private java.lang.String(char[],int,int,java.lang.Void)
constructor = java.lang.String(java.lang.AbstractStringBuilder,java.lang.Void)
constructor = private java.lang.String(java.nio.charset.Charset,byte[],int,int)
constructor = public java.lang.String(byte[],int,int,java.nio.charset.Charset)
constructor = public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
constructor = public java.lang.String(byte[],java.nio.charset.Charset)
constructor = public java.lang.String(byte[],int,int)
constructor = public java.lang.String(byte[])
constructor = public java.lang.String(java.lang.StringBuffer)
constructor = java.lang.String(byte[],byte)
constructor = public java.lang.String(char[],int,int)
constructor = public java.lang.String(char[])
constructor = public java.lang.String(java.lang.String)
constructor = public java.lang.String()
constructor = public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
constructor = public java.lang.String(byte[],int)
constructor = public java.lang.String(byte[],int,int,int)
constructor = public java.lang.String(int[],int,int)

You can also locate a specific constructor, for instance, the one that takes an array of bytes. Note that the syntax byte[].class is used to denote the class that corresponds to an array of bytes.

Class<?> c = String.class;
Constructor<?> constructor = c.getConstructor(byte[].class);
System.out.println("constructor = " + constructor);

Running this code produces the following.

constructor = public java.lang.String(byte[])

 

Obtaining the Parameters of a Constructor

The Constructor class gives you access to the parameters of a given constructor. As for methods, you can get access to the raw type with the method Constructor.getParameterTypes() method, or the generic type, with the Constructor.getGenericParameterTypes() method.

Let us see these two methods in action by querying the constructors of the ArrayList class.

First, let us find the raw types of the parameters.

Class<?> c = ArrayList.class;
Constructor<?>[] constructors = c.getConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println("constructor with " + constructor.getParameterCount() + " parameter");
    for (Class<?> type : constructor.getParameterTypes()) {
        System.out.println("   " + type.getName());
    }
}

Running this code produces the following.

constructor with 1 parameter
   java.util.Collection
constructor with 0 parameter
constructor with 1 parameter
   int

You can get the generic types with the following code. Note that the Constructor.getGenericParameterTypes() method returns an array of Type, on which you can call Type.getTypeName().

Class<?> c = ArrayList.class;
Constructor<?>[] constructors = c.getConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println("constructor with " + constructor.getParameterCount() + " parameter");
    for (Type type : constructor.getGenericParameterTypes()) {
        System.out.println("   " + type.getTypeName());
    }
}

Running this code produces the following.

constructor with 1 parameter
   java.util.Collection<? extends E>
constructor with 0 parameter
constructor with 1 parameter
   int

 

Obtaining Exceptions of a Constructor

The Constructor class gives you access to the declared exceptions of a Constructor. These exceptions are returned in an array, which can be of two types: an array of Class instances, or an array of Type instances. As usual the Type object can give you information about a parameter type.

Let us discover the exceptions thrown by the constructor of FileWriter that takes a String as a parameter.

Class<?> c = FileWriter.class;
Constructor<?> constructor = c.getConstructor(String.class);
for (Class<?> exceptionType : constructor.getExceptionTypes()) {
    System.out.println("Exception type: " + exceptionType.getName());
}
for (Type exceptionType : constructor.getGenericExceptionTypes()) {
    System.out.println("Generic exception type: " + exceptionType.getTypeName());
}

Running this example produces the following:

Exception type: java.io.IOException
Generic exception type: java.io.IOException

 

Invocation Patterns

Invoking a constructor creates a new instance of a class. There are two reflective methods for creating instances of classes: Class.newInstance() and Constructor.newInstance(), which is the pattern you should use.

The first pattern consists in calling the newInstance() method of the Class. This method is actually calling the no-arg constructor of the class it is invoked on. If this constructor does not exist or is not visible (for instance: it is private), then it throws an exception.

The Class.newInstance() method has been deprecated in Java SE 9, and should not be used anymore. There are several reasons for that.

The second pattern that you should be using now, consists in getting a reference on one of the constructor of the class, and invoke it.

Creating an Instance of String

The following example creates an instance of String.

Class<String> stringClass = String.class;
String emptyString = stringClass.getConstructor().newInstance();
System.out.println("Empty? " + emptyString.isEmpty());

Running this code prints the following:

Empty? true

Note the following:

  • stringClass.getConstructor() throws a NoSuchMethodException, in the case the class does not have a no-arg constructor.
  • the call to newInstance() throws several exception:
    • InvocationTargetException: wrapping the exception the invocation of the constructor may have thrown.
    • InstantiationException: in case the corresponding class cannot be instantiated. This is the case for abstract classes or interfaces.
    • IllegalAccessException: in case the no-arg constructor is not accessible from the calling code. This is the case if the constructor is private, dans is accessed from another class.

Creating an Instance of a Record

Suppose that you have the following record.

public record Point(int x, int y) {
    public Point() {
        this(0, 0);
    }
}

Then you can invoke its empty constructor with the following code.

Class<Point> c = Point.class;
Constructor<Point> constructor = c.getConstructor();
Point p = constructor.newInstance();
System.out.println("p = " + p);

Running the previous code prints the following.

p = Point[x=0, y=0]

You can also invoke its canonical constructor with the following code. Note that, despite it is not explicitly written in the code, the compiler generates this canonical constructor for you. You can learn more on records in this section.

Class<Point> c = Point.class;
Constructor<Point> constructor = c.getConstructor(int.class, int.class);
Point p = constructor.newInstance(1, 1);
System.out.println("p = " + p);

Running the previous code produces the following result.

p = Point[x=1, y=1]

Last update: July 25, 2024


Previous in the Series
Current Tutorial
Invoking Constructors
Next in the Series

Previous in the Series: Invoking Methods

Next in the Series: Working with Arrays