Source: Java language semantics (JLS §8.8 — constructors are not members of a class), worked through from an
Animal/Dogexample.
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 |
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 —
privatefields: These are inherited (they exist in the subclass object), but the subclass cannot access them directly — it must go through inheritedpublic/protectedmethods (getters/setters). Some textbooks loosely say "privateisn't inherited"; the precise JLS wording is "inherited but not accessible."
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.)
super(...) Really Doing? — Delegation, Not InheritanceSince 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.
super() and the Default ConstructorIf 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.