Implicit default constructors

As you certainly know, if there is no constructor implemented in a class, the compiler implicitly synthesizes a default constructor. Hence, the following code compiles:

public class ClassA {

    public static void main(String[] args) {
        new ClassA();
    }
}

The disassembled code shows that there is indeed a constructor which essentially calls its super constructor, java.lang.Object.<init>:

$ javap -c ClassA.class
Compiled from "ClassA.java"
public class ClassA {
public ClassA();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #1                  // class ClassA
       3: invokespecial #16                 // Method "<init>":()V
       6: return
}

Now, there is one detail which even long-time Java developers are not always aware of: if any other constructor overload is added to the class, the compiler will not synthesize a default constructor – hence, the following code does not compile:

public class ClassA {

    public ClassA(int a) { }

    public static void main(String[] args) {
        new ClassA();
    }
}

ClassA.java:7: error: constructor ClassA in class ClassA cannot be applied to given types;
        new ClassA();
        ^
  required: int
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error

This is in accordance to the Java Language Specification: 8.8.9. Default Constructor where it says:

If a class contains no constructor declarations, then a default constructor is implicitly declared.
...

Means, if there are any constructor declarations, then no default constructor will be created by the compiler. Note that there is also the same behavior in C++. Note also that the term “default constructor” as it is used by the language specification only refers to the parameterless constructor created by the compiler – hence, strictly spoken, a parameterless constructor which is explicitly implemented in the class is not a default constructor (even though developers often call it like that). Normally, this is not an issue, since the compiler will emit the above error when we try to instantiate the class through the default constructor. However, if the object is created dynamically (e.g. through reflection), there will be no compile time error – it will become a runtime error then:

public class ClassA {

    public ClassA(int a) { }

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clazz = Class.forName("ClassA");
        ClassA obj = (ClassA) clazz.newInstance();
    }
}

Exception in thread "main" java.lang.InstantiationException: ClassA
	at java.lang.Class.newInstance(Unknown Source)
	at ClassA.main(ClassA.java:9)
Caused by: java.lang.NoSuchMethodException: ClassA.<init>()
	at java.lang.Class.getConstructor0(Unknown Source)
	... 2 more
</init>

This can be important when using persistence frameworks which do these kind of things in the background. Other examples are dependency injection frameworks which might complain at the lack of default or empty constructor, if no constructor has the @Inject annotation.