Command Palette

Search for a command to run...

PHASE 5Intermediate ~27 min· topic 9 of 13

Topic 5.9

Abstract Class vs Interface

In one line

Use an interface to define what a type can do, especially when unrelated classes share a capability. Use an abstract class when closely related classes share state and code. Often the best design is both: an interface for the contract and an abstract class that implements most of it.

Think of it like this

A driving licence versus a family business. A driving licence (an interface) says 'this person can drive'. A teacher, a doctor and a delivery rider can all hold one; it says nothing about who they are. A family business (an abstract class) is something you're born into: you inherit the shop, the money and the way things are done, and you can belong to only one family. Use a licence for 'can do', a family for 'is part of'.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Capability
Something an object can do, like being comparable, closeable or printable. Usually modelled as an interface.
Instance state
Data stored separately in each object, in instance fields. Abstract classes can have it; interfaces can't.
Skeletal implementation
An abstract class that implements an interface's methods in terms of a few abstract ones, so concrete classes write very little. Example: AbstractList.
Mixin
A capability that can be added to a class alongside its main type, like Comparable. Interfaces make good mixins.
Contract
The set of methods and their promised behaviour that callers rely on.

Step by step

01The comparison table

Instantiate with new: neither.

Instance fields: abstract class yes; interface no (constants only).

Constructors: abstract class yes; interface no.

Method bodies: abstract class yes; interface yes since Java 8 (default, static), private since Java 9.

Member access: abstract class any; interface public (plus private helpers).

final methods: abstract class yes; interface no.

How many per class: one abstract class; any number of interfaces.

Can be a lambda target: abstract class no; interface yes, if it has exactly one abstract method (Phase 10).

02Pick an interface when…

…unrelated classes share a capability: Comparable, AutoCloseable, Runnable, Iterable. A String, a File and your Invoice class have nothing in common except that each can be compared, closed or iterated.

…you're defining a boundary between parts of a system (a PaymentGateway, a UserRepository) that other teams or test doubles will implement.

…you want callers to pass a lambda. Only interfaces can be functional types.

03Pick an abstract class when…

…several closely related classes share fields and the code that manages them (an id, a created-at time, a list of listeners).

…you need a constructor to enforce invariants for every subclass (validate the name once, in one place).

…you need non-public helper methods, or a final template method that subclasses must not change.

04Best of both: interface plus skeletal class

java.util.List is an interface with about 30 methods. Writing all of them is a lot of work. java.util.AbstractList implements nearly all of them on top of just get(int) and size(). To make your own read-only list, extend AbstractList and write two methods. If your class already extends something else, implement List directly instead; callers can't tell the difference because they only see List.

Name the pair the way the JDK does: Shape and AbstractShape.

Best of both: interface plus skeletal classdiagram
Rendering diagram…

05A decision flow

When in doubt, start with an interface. It's easy to add an abstract helper class later; it's hard to turn an abstract class into an interface after other code extends it, because those subclasses may already extend nothing else and rely on its fields.

A decision flowdiagram
Rendering diagram…

Try it yourself

  1. 1

    Make Range modifiable? No: make it reversed

    Add a class Countdown extends AbstractList<Integer> whose get(i) returns n - i and size() returns n. Print new Countdown(5) and predict [5, 4, 3, 2, 1].

  2. 2

    Move state into the interface

    Try adding private int trips; to the Vehicle interface and compile. Then try int trips; (no modifier). Explain both errors: the first is not allowed, the second is a constant that must be initialised.

Code & diagrams

Interface plus skeletal implementation New tab
Sign in to run this example in your browser.

Expected output

Bus (6 wheels, 2 trips)
ToyCar (plastic)
A full List in two methods with AbstractList New tab

AbstractList's add() throws UnsupportedOperationException unless you override it, which is how JDK read-only lists behave too.

Sign in to run this example in your browser.

Expected output

[3, 4, 5, 6, 7]
true
4
[4, 5]
sum = 25
add() not supported: read-only list
One parent, several capabilities New tab
Sign in to run this example in your browser.

Expected output

Printing Invoice #1
Invoice #2 as PDF
Amount: 500
Invoice #1 / Invoice #1 as CSV

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Treat an interface field as state

Declare int MAX = 10; in an interface and try to change it.

Main.javawhole filejava
interface Limits { int MAX = 10; }
public class Main { public static void main(String[] a) { Limits.MAX = 20; } }
terminal
$ javac Main.java
── what you'll see ──
Main.java:2: error: cannot assign a value to static final variable MAX
public class Main { public static void main(String[] a) { Limits.MAX = 20; } }
^
1 error

Break #2

Extend two abstract classes

Write class C extends A, B with two abstract parents.

Main.javawhole filejava
class A { } class B { }
class C extends A, B { }
terminal
$ javac Main.java
── what you'll see ──
Main.java:2: error: '{' expected
class C extends A, B { }
^
1 error

Myth vs fact

Myth

Since Java 8, interfaces and abstract classes are the same thing.

Fact

Interfaces still have no instance fields, no constructors, no final or protected methods. Abstract classes still occupy the single superclass slot.

Myth

Interfaces are always faster or slower than abstract classes.

Fact

After JIT profiling, monomorphic interface and class calls cost the same. Choose by design, not speed.

Myth

You must choose one or the other.

Fact

The JDK's favourite design is both: an interface for callers plus an abstract skeletal class for implementers.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Evolution cost differs: adding a concrete method to an abstract class is safe for subclasses (unless a subclass already has a same-signature method with an incompatible return type). Adding a default to an interface is mostly safe but can create unresolvable conflicts in classes implementing two interfaces (Topic 5.8). Adding an abstract method to either breaks implementers.

  • ▸

    Abstract classes can declare protected abstract hooks that stay out of the public API. Interfaces can't express 'only subclasses may call this', which is a real reason frameworks keep abstract base classes for template-style extension points (e.g. Spring's OncePerRequestFilter).

  • ▸

    Sealed interfaces (Topic 5.11) let a library expose an interface type while still controlling every implementation, combining the 'interface for callers' benefit with the 'closed family' benefit that used to require a package-private abstract class.

Remember this

  1. 1

    State: an abstract class can have instance fields (per-object data) and constructors. An interface can't: its fields are public static final constants and it has no constructors.

  2. 2

    How many: a class can extend one abstract class but implement any number of interfaces. Choosing an abstract class uses up the single parent slot; choosing an interface doesn't.

  3. 3

    Access: abstract class members can be private, protected, package-private or public. Interface methods are public, except Java 9 private helpers. Abstract classes can also have final methods (a fixed template, Topic 5.6); interfaces can't make a method final.

  4. 4

    Since Java 8 the gap narrowed: interfaces can have default and static method bodies (Topic 5.8). So the deciding question is no longer 'do I need any code?' but 'do I need state, constructors, non-public members, or final template methods?'. If not, prefer an interface.

  5. 5

    The skeletal implementation idiom combines both: publish an interface (List), and provide an abstract class that implements it (AbstractList) so implementers only write the essential methods. Classes that already have a parent can still implement the interface directly. The JDK does this throughout the collections framework.

  6. 6

    Interview shortcut: interface = can-do relationship and a contract between teams; abstract class = is-a relationship within one family that shares code and data.

Explain it without notes

01

Give four concrete differences between an abstract class and an interface in modern Java.

02

When would you choose an abstract class over an interface?

03

What is a skeletal implementation? Give a JDK example.

04

Why is 'start with an interface' usually the safer default?

Practice

01

Design Notifier as an interface and AbstractNotifier as a skeletal class that stores a sentCount and implements send(String) by calling an abstract deliver(String) and incrementing the count. Implement EmailNotifier.

02

Using AbstractList, write Repeat(String s, int n) that looks like a list of n copies of s. Print it and its size().

03

Decide interface or abstract class for each and justify in one line: (a) Closeable, (b) a base HttpServlet with service() dispatching to doGet/doPost, (c) PaymentGateway with Stripe and Razorpay implementations.

Trade-offs

  • ↔

    Interfaces maximise flexibility for implementers but can't protect invariants with constructors or hide hooks. Abstract classes protect invariants but lock implementers into one hierarchy.

  • ↔

    Offering both an interface and a skeletal class doubles the public types to document and maintain, but gives implementers the choice. Worth it for widely implemented types; overkill for a type with one or two implementations.

Done when you can

  • Done when you can list the differences in state, constructors, access, finality and count.

  • Done when you can pick between the two for a given design and justify it.

  • Done when you can build a working list with AbstractList in two methods.

  • Done when you can explain the skeletal implementation idiom.