Source: Java language semantics (JLS §8.8 — constructors are not members of a class), worked through from an Animal / Dog example.

1. The Apparent Paradox

A subclass inherits instance variables (fields) from its superclass, but does not inherit constructors. This sounds contradictory at first — how can one be passed down and not the other? The resolution is that fields and constructors describe different kinds of things:

Thing Describes Inherited?
Instance variables The structure / state of an object ✅ Yes
Constructors The process of building one specific class ❌ No

2. Why Fields Are Inherited

A subclass has an IS-A relationship with its superclass: a Dog object literally is an Animal object plus some extra. So every field declared in the superclass genuinely exists inside every subclass object in memory.

Analogy: the superclass fields are the foundation and ground floor of a house; the subclass just builds more floors on top. The lower floors are still physically there.

Gotcha — private fields: These are inherited (they exist in the subclass object), but the subclass cannot access them directly — it must go through inherited public/protected methods (getters/setters). Some textbooks loosely say "private isn't inherited"; the precise JLS wording is "inherited but not accessible."

3. Why Constructors Are Not Inherited — A Proof by Absurdity

Suppose, hypothetically, that constructors were inherited. Then Dog would inherit Animal's constructor — a constructor literally named Animal.

But a constructor's name must exactly match the name of its own class. A method named Animal sitting inside Dog is nonsense — it can't be a valid constructor for Dog.

The assumption leads to an absurdity, so it must be false. Constructors are not inherited. (Formally, the JLS states constructors are not members of a class, so they can't be inherited, overridden, or hidden.)

4. So What Is super(...) Really Doing? — Delegation, Not Inheritance

Since Dog doesn't own Animal's constructor, how does Animal's initialization logic ever run? Through delegation: when you construct a Dog, the Dog constructor's first action is to call the Animal constructor via super(...).

class Animal {
    int legs;
    Animal(int legs) { this.legs = legs; }
}

class Dog extends Animal {
    String name;
    Dog(String name) {
        super(4);        // must call it yourself — NOT auto-inherited
        this.name = name;
    }
}

Dog uses the inherited field legs, but it does not possess the Animal(int) constructor — it merely calls it. Think of it as "getting help from the Animal class" to initialize the Animal-layer of the object; Dog then initializes its own layer.

Rule: an explicit super(...) must be the first statement in the constructor. The superclass layer has to be fully initialized before the subclass can build on top of it.

5. The Implicit super() and the Default Constructor

If you write no constructor in Dog, the compiler gives Dog a default no-arg constructor, and inserts a call to super() — note the empty parentheses — inside it. That implicit call goes looking for the superclass's no-arg constructor Animal().

This auto-magic only works if Animal actually has an accessible no-arg constructor.