javapolymorphismabstract-classabstract-methods

Why can we call abstract method from an abstract class before sub-class initialization


We can initialize an abstract class through initialization of a concrete sub class. Therefore, should be able to call the abstract methods of an abstract class only after the initialization of a subclass However, the following initialization block in abstract class Mammal can call an abstract method before the initialization of the sub child class.

If you call the constructor of Platypus with new Platypus(), it outputs: "yummy!", "Mammal constructor", "Platypus constructor" in the same order. I thought an instance of a class gets created when the constructor is called. But the initialization block in Mammal is able to call the method before Platypus initialization.

abstract class Mammal {

    {
        System.out.println(chew()); 
    }

    abstract CharSequence chew();

    public Mammal() {
       System.out.println("Mammal constructor"); 
    }
}

public class Platypus extends Mammal {

    public Platypus() {
        System.out.println("Platypus constructor");
    }
    
    String chew() {
        return "yummy!";
    }


}

Solution

  • There is nothing special about abstract methods here. You can also just call non-abstract methods in the same way:

    class Platypus {
        {
            System.out.println(chew());
        }
        
        public Platypus() {
            System.out.println("Platypus constructor");
        }
    
        String chew() {
            return "yummy!";
        }
    }
    

    I thought an instance of a class gets created when the constructor is called.

    No, the constructor is not responsible for creating the object. An object is created first, and then its constructor is called to initialise the object.

    This can be seen in the bytecode too. The bytecode for new Platypus() looks something like this:

    NEW yourpackage/Platypus
    DUP
    INVOKESPECIAL yourpackage/Platypus.<init> ()V
    

    The new instruction creates the object, and then <init>, which is the JVM name for constructors, is invoked.

    So here, we can say that chew() is called before the object is fully initialised. The object already exists, so calling chew is technically possible.

    However, calling instance methods when the object is not fully initialised is usually not a good idea. The method might depend on the fact that the object is fully initialised (e.g. accessing fields that are expected to not be null). See also: Can I call methods in constructor in Java?