• Home
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All
  • About
Java | Constructors
  1. Constructors
  2. Constructor Declaration Rules
  3. Important Notes about Constructor Code
  4. Important Notes about Constructor Execution
  5. Important Notes about Constructor Exception Handling
  6. Important Notes about Constructor and Initialization Order

  1. Constructors
    All classes (including abstract classes) must declare at least one constructor.
    By default, if the class does not declare any constructors, the compiler creates a no-argument constructor (also called a default constructor).

    Note: the compiler will not create any constructors if the class declares at least one constructor.

    For example, for the class ClassA, the compiler will automatically create the no-argument constructor ClassA() {}:
    class ClassA {
    }
    Class ClassB will not have a no-argument constructor:
    class ClassB {
        ClassB(int arg1) { }
    }
    Important: Constructors are not inheritable; a subclass does not inherit the constructors of its superclasses. Therefore, the concepts of inheritance and overriding do not apply to constructors.
  2. Constructor Declaration Rules
    1. A constructor cannot return a value, and therefore it must not declare a return type.
      You cannot even use the keyword void.

    2. A constructor can have zero or more parameters.

    3. The constructor declaration can use any access modifier: public, protected, private, or package-private (no modifier).

    4. The constructor declaration cannot use other modifiers such as final, static, etc.
      public class ClassD {
          final ClassD() { } // compiler error: Illegal modifier for the constructor in type ClassD; only public, protected & private are permitted
      }
    5. The name of the constructor must match the name of the class in which it is declared.

      Note: Java is case-sensitive, so the constructor name and the class name must match exactly.
      class ClassC {
          // A valid constructor declaration
          ClassC() { }
      
          // The compiler treats this as a method, not a constructor
          classc() { } // compiler error: Return type for the method is missing
      
          // A valid method declaration
          void clASSc() { }
      }
      It is possible to declare a method with the exact same name as the class; the difference between a method and a constructor is:
      • A constructor does not declare a return type.

      • A constructor can be invoked using the new operator (instantiation).

      • A constructor can only be invoked from another constructor (it cannot be called from a method or an initialization block).

    6. It is possible to declare multiple constructors (constructor overloading) in the same class, as long as their signatures are different.
      class ClassC {
          ClassC() { }
      
          ClassC(int arg1) { }
      
          ClassC(int arg1, boolean arg2) { }
      }
  3. Important Notes about Constructor Code
    1. The compiler may insert a call to the no-argument constructor of the superclass (super()) at the beginning of a constructor.

      Note: The compiler will not insert a call to the superclass constructor if the constructor code already includes:
      • an explicit call (using the this keyword) to another constructor in the same class;

      • or an explicit call (using the super keyword) to a superclass constructor.

      class SuperClass {
          SuperClass() {
              // the compiler adds this statement: super();
              System.out.println();
          }
      }
      
      class SubClass extends SuperClass {
          SubClass() {
              // the compiler adds this statement: super();
          }
      
          SubClass(boolean arg1) {
              this(); // Because of this call, the compiler doesn't add a call to the superclass constructor
          }
      
          SubClass(int arg1) {
              super(); // Because of this call, the compiler doesn't add another call to the superclass constructor
          }
      }
    2. If the superclass does not declare a no-argument constructor, you must explicitly call a superclass constructor that takes arguments.

      Otherwise, the compiler will show an error, because, as mentioned above, it tries to insert a call to the no-argument constructor — which doesn’t exist in this case!
      class SuperClass1 {
          SuperClass1() { }
      }
      
      class SuperClass2 extends SuperClass1 {
          SuperClass2(int arg1) {
              // OK: SuperClass1 declares a no-arg constructor
          }
      }
      
      class SubClass extends SuperClass2 {
          SubClass() { } // compiler error: Implicit super constructor SuperClass2() is undefined. Must explicitly invoke another constructor
      
          SubClass(boolean arg1) {
              this(); // OK: because of this(), the compiler doesn't add a call to the superclass constructor
          }
      
          SubClass(int arg1) {
              super(arg1); // OK: because of super(), the compiler doesn't add a no-arg call
          }
      }
      To understand the error, here’s how the constructor is seen by the compiler:
      class SubClass extends SuperClass2 {
          SubClass() {
              super(); // compiler error: The constructor SuperClass2() is undefined
          }
      
          SubClass(boolean arg1) {
              this();
          }
      
          SubClass(int arg1) {
              super(arg1);
          }
      }
    3. If the this or super keywords are used in constructor code, they must be the first statements in the constructor, otherwise the compiler will generate an error.
      class SuperClass2 {
          SuperClass2() { }
      }
      
      class SubClassF extends SuperClass2 {
          SubClassF() {
              System.out.println();
              super(); // compiler error: Constructor call must be the first statement in a constructor
          }
      
          SubClassF(boolean arg1) {
              System.out.println();
              this(); // compiler error: Constructor call must be the first statement in a constructor
          }
      }
    4. The compiler will generate an error if constructors call each other recursively.
      class ClassG {
          ClassG() {
              this(true); // compiler error: Recursive constructor invocation ClassG(boolean)
          }
      
          ClassG(boolean arg1) {
              this(); // compiler error: Recursive constructor invocation ClassG()
          }
      }
    5. You cannot pass instance variables (or call instance methods) as arguments to this(); or super();.

      Only constructor parameters, class variables, and static methods can be passed as arguments to this(); or super();.

      In constructor code, you cannot use an instance variable or call an instance method before the superclass constructor has completed execution.
      class SuperClass {
          SuperClass() { }
      
          SuperClass(int arg1) { }
      }
      
      class SubClass extends SuperClass {
          int var1 = 1;
          static int var2 = 1;
      
          SubClass() {
              this(var1); // compiler error: Cannot refer to an instance field var1 while explicitly invoking a constructor
          }
      
          SubClass(int arg1) {
              super(var1); // compiler error: Cannot refer to an instance field var1 while explicitly invoking a constructor
          }
      
          SubClass(short arg1) {
              super(arg1); // OK
          }
      
          SubClass(float arg1) {
              this(instanceMethod()); // compiler error: Cannot refer to an instance method while explicitly invoking a constructor
          }
      
          SubClass(double arg1) {
              this(staticMethod()); // OK
          }
      
          SubClass(int arg1, int arg2) {
              this(staticMethod() + arg1 + arg2 + var2); // OK
              var1 = instanceMethod(); // OK
              var2 = staticMethod(); // OK
          }
      
          public Integer instanceMethod() {
              return 0;
          }
      
          public static Integer staticMethod() {
              return 0;
          }
      }
  4. Important Notes about Constructor Execution
    1. Constructors are executed when a new instance of a class is created: instantiation is done using the new keyword.

      The arguments passed with new determine which constructor is executed.
      class ClassH {
          ClassH() { }
      
          ClassH(int arg1) { }
      }
      
      public class Test1 {
          public static void main(String[] args) {
              new ClassH(); // ClassH() will be executed
      
              new ClassH(1); // ClassH(int arg1) will be executed
          }
      }
    2. It is possible to execute multiple constructors during instantiation: the constructor invoked using the new keyword can call another constructor in the same class using this. That constructor can in turn use this to call another constructor, and so on. See the section above for notes on recursive constructor calls.

      The arguments passed with this determine which constructor is executed.

      Reminder: The this statement (like super) must be the first line in the constructor body (see details above).
      class ClassI {
          ClassI() { this(1); } // invokes ClassI(int arg1)
      
          ClassI(int arg1) { }
      }
      
      public class Test1 {
          public static void main(String[] args) {
              new ClassI(); // ClassI() will be executed
      
              new ClassI(1); // ClassI(int arg1) will be executed
          }
      }
    3. Instantiation guarantees that at least one constructor from each superclass will be executed: the constructor called using new may invoke a constructor from its superclass using super. That constructor may in turn call another constructor in its own superclass, and so on.

      The arguments passed with super determine which superclass constructor is executed.

      Reminder: The compiler adds the statement super(); by default at the beginning of the constructor body, if it doesn't already contain a call to this or super.
      class SuperClass {
          SuperClass() { } // the compiler will insert "super();" at the beginning
      
          SuperClass(int arg1) { } // the compiler will insert "super();" at the beginning
      }
      
      class SubClass extends SuperClass {
          SubClass() { } // the compiler will insert "super();" at the beginning
      
          SubClass(int arg1) { super(arg1); } // the superclass constructor SuperClass(int arg1) will be executed
      }
  5. Important Notes about Constructor Exception Handling
    1. Constructors can throw exceptions, including both checked and unchecked exceptions.
      When a constructor throws an exception, the object is not created, and no reference to the object is returned.

    2. If a constructor throws an exception, any initialization that occurred before the exception is thrown may leave the system in an inconsistent state.

      Important: When an exception is thrown from a constructor, the object is considered not to have been created, so finalizers will not be called.

    3. When calling superclass constructors that can throw exceptions, the subclass constructor must handle or declare the exception.

    4. If a constructor calls another constructor using this() and that constructor throws an exception, the calling constructor will not continue execution.

    5. When acquiring resources in constructors, proper exception handling is crucial to prevent resource leaks.
  6. Important Notes about Constructor and Initialization Order
    1. The complete initialization order when creating an object follows a specific sequence:

      1. Static initialization (only once per class loading).
      2. Instance variable initialization and instance initialization blocks (in order of declaration).
      3. Constructor execution.

    2. In inheritance hierarchies, the initialization order becomes more complex:

      1. Static initialization of superclass (if not already done).
      2. Static initialization of subclass (if not already done).
      3. Instance initialization of superclass.
      4. Superclass constructor execution.
      5. Instance initialization of subclass.
      6. Subclass constructor execution.

    3. Instance initialization blocks run before constructors and can be used to initialize instance variables that are common to all constructors.

      Note: Instance initialization blocks have access to instance variables and methods, unlike static initialization blocks.

    4. When using constructor chaining with this(), the initialization order is:

      1. Instance variable initialization and instance blocks.
      2. The constructor called by this().
      3. The current constructor body (after the this() call).

      Important: Instance initialization happens only once, before the first constructor in the chain executes.
© 2025  mtitek