Definition
Inheritance hierarchy:
- Base class (parent): Defines common fields (accountId, balance) and methods (getBalance, debit).
- Derived class (child): Uses
extendsto inherit the base class. Adds new fields (interestRate) and can override methods (calculateInterest). - IS-A: SavingsAccount IS-A Account. It can be used anywhere Account is expected.
The base class Account is the standard bank template. SavingsAccount and CurrentAccount are specialized versions that inherit the template and add their own features.
Understanding the Concepts
Base and derived class example
// Base class
public class Account {
protected String accountId;
protected BigDecimal balance;
public Account(String accountId, BigDecimal balance) {
this.accountId = accountId;
this.balance = balance;
}
public void debit(BigDecimal amount) {
balance = balance.subtract(amount);
}
public BigDecimal getBalance() { return balance; }
}
// Derived class
public class SavingsAccount extends Account {
private double interestRate;
public SavingsAccount(String accountId, BigDecimal balance, double rate) {
super(accountId, balance); // call base constructor
this.interestRate = rate;
}
public BigDecimal calculateInterest() {
return balance.multiply(BigDecimal.valueOf(interestRate / 100));
}
}
// IS-A: SavingsAccount can be used as Account
Account a = new SavingsAccount("SAV2001", new BigDecimal("500000"), 4.0);
a.debit(new BigDecimal("50000")); // inherited method
What does a derived class inherit?
| Inherited | Not inherited |
|---|---|
| public and protected fields | private fields (exist but not accessible) |
| public and protected methods | private methods |
| Default (package-private) if same package | Constructors (must call super()) |
What should a senior engineer know?
- Prefer composition over inheritance when the IS-A relationship is not clear. Use
has-a(field) instead ofis-a(extends). - Abstract base classes define the contract without full implementation.
- Sealed classes (Java 17+) control which classes can extend the base:
sealed class Account permits SavingsAccount, CurrentAccount.
What are common mistakes?
A common mistake is not understanding the concept fully before using it in production banking applications.
Wrong approach:
package com.bank.service;
public class TransferService {
public void transfer(String fromAccount, String toAccount, double amount) {
// WRONG: using double for money
double balance = getBalance(fromAccount);
balance = balance - amount;
}
private double getBalance(String id) { return 10000.0; }
}
Correct approach:
package com.bank.service;
import java.math.BigDecimal;
public class TransferService {
public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
// CORRECT: using BigDecimal for money
BigDecimal balance = getBalance(fromAccount);
balance = balance.subtract(amount);
}
private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}
Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.
What are the edge cases?
Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.
package com.bank.edge;
public class EdgeCaseDemo {
public static void main(String[] args) {
// Edge case 1: null handling
String accountId = null;
try {
System.out.println(accountId.length());
} catch (NullPointerException e) {
System.out.println("Null account ID");
}
// Edge case 2: empty vs null
String emptyId = "";
System.out.println(emptyId.isEmpty()); // true
System.out.println(emptyId == null); // false
// Edge case 3: boundary values
java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
System.out.println(zero.compareTo(negativeBalance) > 0); // true
}
}
Null account ID
true
false
true
Always test with null values, empty strings, boundary values, and negative amounts in banking applications.
What are common interview follow-up questions?
Interviewers often follow up with these related questions:
- How does this concept apply to a high-throughput banking transaction system?
- What are the performance implications in a production environment?
- How would you debug issues related to this concept?
- What tools would you use to monitor this in production?
- How does this behave differently in Java 8 vs Java 17+?
When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.
Visual Overview
Account (base)
├── accountId, balance
├── debit(), getBalance()
│
├── SavingsAccount extends Account (derived)
│ + interestRate
│ + calculateInterest()
│
└── CurrentAccount extends Account (derived)
+ overdraftLimit
+ checkOverdraft()
IS-A: SavingsAccount IS-A Account
→ can be used anywhere Account is expected
Key Takeaway
A base class defines shared state and behavior. A derived class extends it with the extends keyword, inheriting all non-private members and adding or overriding specific behavior. This creates an IS-A relationship: a SavingsAccount is an Account and can be used anywhere an Account is expected.
One sentence to remember: the base class is the shared template, the derived class specializes it – inheritance means IS-A.
---