Back to Abstraction & Interfaces
Q1Question 1 of 4

What is the difference between abstract class and interface?

Key Concepts
  • Interface defines a contract with no instance state; abstract class provides partial implementation with shared mutable fields
  • A class can extend only one abstract class but implement multiple interfaces
  • Interfaces cannot have constructors; abstract classes can initialize shared state via constructors
  • Java 8 added default and static methods to interfaces, but they still cannot have instance fields
  • Choose interface for capabilities (Auditable, Serializable); choose abstract class for family hierarchies with shared state
  • Modern guideline: prefer interface with default methods unless you need constructors or shared mutable state

Definition

Interface provides a contract with multiple inheritance and no state. Abstract class provides partial implementation with single inheritance and can have state and constructors. Prefer interface unless you need shared mutable fields.

Since Java 8, interfaces have narrowed the gap with abstract classes. The remaining differences drive the choice.

  • State: abstract class can have instance fields (mutable state). Interface can only have public static final constants.
  • Constructors: abstract class can have constructors that initialize shared state. Interface cannot.
  • Single vs multiple: a class can extend only one abstract class but implement multiple interfaces.
  • Access modifiers: abstract class methods can be any access level. Interface methods are implicitly public (private since Java 9 for helpers).
  • Default methods (Java 8): interfaces can have method bodies, but they still cannot have instance fields or constructors.
  • Choose interface when defining a capability contract that unrelated classes can implement. Choose abstract class when sharing mutable state and constructors among a family of related classes.

An interface is like a banking license: any institution that implements DepositService must provide deposit() and withdraw(). A bank, a payment app, and a cooperative can all hold this license. Multiple licenses allowed. An abstract class is like a bank template at National Bank of India: all branches share common code (balance tracking, audit logging), but each branch fills in its own interest rate. Only one template per branch (single inheritance). The template has state (balance field) and a constructor (initializes accountId).

Understanding the Concepts

What is the difference between abstract class and interface?

Since Java 8, the feature gap has narrowed significantly. But four key differences remain.

What are the four remaining differences?

JAVA
package com.bank.core;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

// Difference 1: CONSTRUCTORS (abstract class: yes, interface: no)
public abstract class Account {
    private final String accountId;
    protected BigDecimal balance;

    protected Account(String accountId, BigDecimal initialBalance) {
        if (accountId == null) throw new IllegalArgumentException("required");
        this.accountId = accountId;
        this.balance = initialBalance;
    }
    // Interface: no constructor. Cannot initialize state on creation.
}

// Difference 2: INSTANCE FIELDS (abstract class: yes, interface: no)
// Account has: protected BigDecimal balance (mutable instance field)
// Interface has: BigDecimal MAX = new BigDecimal("10000000"); // public static final only

// Difference 3: ACCESS MODIFIERS (abstract class: any, interface: public only)
// Account can have: protected void internalValidate() { }
// Interface: all methods implicitly public (private since Java 9 for helpers)

// Difference 4: SINGLE vs MULTIPLE INHERITANCE
// class SavingsAccount extends Account implements Auditable, Notifiable, Taxable { }
// Cannot: class X extends Account, AnotherClass { } // compile error

How does an interface look in Java 8+?

JAVA
public interface PaymentChannel {
    // Abstract method: implementor must provide body
    TransferResult transfer(String from, String to, BigDecimal amount);

    // Default method (Java 8): has body, inherited by implementors
    default boolean isAvailable() {
        return true; // implementors can override
    }

    // Static method (Java 8): utility, called via InterfaceName.method()
    static PaymentChannel defaultChannel() {
        return new NeftChannel();
    }

    // Private method (Java 9): helper for default methods
    private void logTransfer(String msg) {
        System.out.println("[PaymentChannel] " + msg);
    }

    // Constants only: no instance fields
    BigDecimal MAX_TRANSFER = new BigDecimal("10000000"); // implicitly public static final
}

How does an abstract class look?

JAVA
public abstract class Account {
    private final String accountId;
    protected BigDecimal balance;
    private final List<String> auditLog = new ArrayList<>();

    protected Account(String accountId, BigDecimal initialBalance) {
        this.accountId = accountId;
        this.balance = initialBalance;
        auditLog.add("OPENED: Rs." + initialBalance);
    }

    public void deposit(BigDecimal amount) {
        balance = balance.add(amount);
        auditLog.add("CREDIT: Rs." + amount);
    }

    public abstract BigDecimal calculateInterest(); // subclass must implement

    // Template Method Pattern: concrete method calling abstract method
    public void processMonthEnd() {
        BigDecimal interest = calculateInterest();
        if (interest.signum() > 0) {
            deposit(interest);
        }
    }
}

When does the choice actually matter?

| Decision Factor | Choose Interface | Choose Abstract Class |
|----------------|-----------------|----------------------|
| Need instance fields? | No | Yes |
| Need constructor? | No | Yes |
| Multiple unrelated classes? | Yes (multiple interfaces) | No (single extends) |
| Defining a capability? | Yes (Auditable, Comparable) | No |
| Defining a family hierarchy? | No | Yes (Account hierarchy) |
| Template Method Pattern? | No | Yes |
| Default choice? | Yes (prefer interface) | Only when state needed |

What does a real-world example look like?

JAVA
// Account: abstract class (has state, constructor, template method)
public abstract class Account {
    protected BigDecimal balance;
    protected Account(BigDecimal balance) { this.balance = balance; }
    public abstract BigDecimal calculateInterest();
}

// Auditable: interface (capability, any class can have it)
public interface Auditable {
    List<String> generateAuditReport();
}

// Taxable: interface (capability, any class can have it)
public interface Taxable {
    BigDecimal calculateTax();
}

// SavingsAccount: uses both
public class SavingsAccount extends Account implements Auditable, Taxable {
    // Extends ONE abstract class (Account: shared state + template).
    // Implements MULTIPLE interfaces (Auditable + Taxable: capabilities).
}

What are common mistakes?

The most common mistake is using an abstract class when an interface would suffice, wasting the single inheritance slot.

JAVA
// WRONG: wasting inheritance on a contract with no state
public abstract class Auditable {
    public abstract List<String> generateReport();
}
// Now SavingsAccount extends Account but cannot also extend Auditable.

// CORRECT: use interface for stateless contracts
public interface Auditable {
    List<String> generateReport();
}
// SavingsAccount extends Account implements Auditable. Both slots used well.

What should a senior engineer know?

  • In Spring, services implement interfaces for loose coupling. JpaRepository is an interface (multiple implementations possible).
  • The Template Method Pattern is the primary use case for abstract classes in modern Java.
  • Records (Java 16) can implement interfaces but cannot extend classes (they already extend Record).
  • Sealed interfaces (Java 17) control which classes can implement them, enabling exhaustive pattern matching.

Visual Overview

DIAGRAM
  ABSTRACT CLASS vs INTERFACE
  ──────────────────────────────────────────
  Abstract Class                  Interface
  ┌──────────────────┐   ┌──────────────────┐
  │ Instance fields   │   │ Constants only    │
  │ Constructors      │   │ No constructors   │
  │ Any access level  │   │ public only       │
  │ Single extends    │   │ Multiple implements│
  │ Template Method   │   │ Default methods   │
  └──────────────────┘   └──────────────────┘

  class SavingsAccount
       extends Account          <- single abstract class
       implements Auditable,    <- multiple interfaces
                  Notifiable,
                  Taxable

Key Takeaway

Since Java 8, the feature gap between abstract class and interface has narrowed: interfaces now have default methods, static methods, and private methods. The remaining differences drive the choice: abstract classes can have instance fields and constructors (shared mutable state); interfaces cannot. A class can extend only one abstract class but implement multiple interfaces. Use abstract class when you need shared state across subclasses (balance field, audit log) and a constructor to initialize it. Use interface when you define a capability (Auditable, Serializable, Comparable) that multiple unrelated classes may need.

In Pankaj's banking platform at National Bank of India, Account is an abstract class because it has shared mutable state (balance, auditLog), a constructor, and a template method (processMonthEnd calls calculateInterest and deposit). Auditable, Notifiable, and Taxable are interfaces because SavingsAccount needs two of them, CurrentAccount needs all three, and the single abstract class inheritance slot is already used by Account.

Remember one sentence: prefer interfaces with default methods as the default choice, and use abstract classes only when you need constructors or shared mutable instance fields.

---

Share
Use ← → arrow keys to navigate