Definition
Abstract class constructors:
- Allowed. An abstract class can have zero, one, or many constructors, including parameterized ones.
- Not directly instantiated.
new AbstractAccount()does not compile. You instantiate a concrete subclass. - Called via super(). When you write
new SavingsAccount(...), the SavingsAccount constructor callssuper(...)which runs the abstract class constructor. - Purpose. Initialize common fields (accountId, holderName) that all subclasses share.
The bank's standard account template (abstract class) has a setup form (constructor) that fills in the account ID and holder name. You cannot file the template directly – you must use a specific account type form (concrete subclass) that includes the template form as its first section.
Understanding the Concepts
How does it work?
public abstract class Account {
private final String accountId;
private final String holderName;
// Abstract class constructor – called via super() from subclasses
protected Account(String accountId, String holderName) {
this.accountId = accountId;
this.holderName = holderName;
System.out.println("Account initialized: " + accountId);
}
public abstract BigDecimal calculateInterest();
public String getAccountId() { return accountId; }
}
public class SavingsAccount extends Account {
private double rate;
public SavingsAccount(String accountId, String holderName, double rate) {
super(accountId, holderName); // calls abstract class constructor
this.rate = rate;
}
@Override
public BigDecimal calculateInterest() {
return new BigDecimal(rate / 100);
}
}
// new Account("SAV2001", "Rajesh"); // COMPILE ERROR: Account is abstract
SavingsAccount sa = new SavingsAccount("SAV2001", "Rajesh", 4.0); // OK
// Output: Account initialized: SAV2001
Why would an abstract class need a constructor?
- Initialize common fields. accountId, holderName, createdAt – shared by all account types.
- Validate inputs. Ensure accountId is not null, holderName is not empty.
- Enforce invariants. Every account must have a valid ID, regardless of the subclass type.
protected Account(String accountId, String holderName) {
this.accountId = Objects.requireNonNull(accountId, "accountId must not be null");
if (holderName == null || holderName.isBlank()) {
throw new IllegalArgumentException("holderName must not be blank");
}
this.holderName = holderName;
}
No subclass can bypass this validation because they all must call super().
What about interfaces?
Interfaces cannot have constructors. Only abstract classes can.
| Feature | Abstract class | Interface |
|---|---|---|
| Constructor | Yes | No |
| Instance fields | Yes | No (only static final constants) |
| Instantiate directly | No | No |
| Multiple inheritance | No (single extends) | Yes (multiple implements) |
What are common mistakes?
- Trying to instantiate an abstract class.
new Account(...)does not compile. - Making the constructor public. Use
protectedsince only subclasses should call it. - Forgetting super() in the subclass. If the abstract class has no no-arg constructor, the subclass must explicitly call super(args).
What should a senior engineer know?
- Template method pattern uses abstract class constructors: the abstract class defines the skeleton (including field initialization in the constructor), and subclasses fill in the abstract methods.
- Abstract class with all-concrete methods is legal. It just prevents direct instantiation. Use this when you want to force subclassing.
- Sealed abstract classes (Java 17+) restrict which classes can extend them:
public sealed abstract class Account permits SavingsAccount, CurrentAccount {}.
Visual Overview
new SavingsAccount("SAV2001", "Rajesh", 4.0)
│
▼
SavingsAccount constructor
│ super("SAV2001", "Rajesh")
▼
Account constructor (abstract class)
│ validates accountId, holderName
│ assigns common fields
▼
Returns to SavingsAccount constructor
│ assigns rate = 4.0
▼
Object fully constructed
new Account("SAV2001", "Rajesh") → COMPILE ERROR: Account is abstract
Key Takeaway
Yes, abstract classes can have constructors. They are called via super() from concrete subclass constructors, never directly. The purpose is to initialize common fields, validate inputs, and enforce invariants that all subclasses must respect.
Make abstract class constructors protected since only subclasses should call them. And remember: interfaces cannot have constructors – this is one of the key differences between abstract classes and interfaces.
One sentence to remember: abstract classes can have constructors called via super() from subclasses – they initialize shared state and enforce validation that no subclass can bypass.
---