Abstract classes vs interfaces
An interface declares what a type can do. Since Java 8 it can also contain default and static methods, and since Java 9 private methods that share code between defaults. Fields in interfaces are always public static final constants.
An abstract class can hold instance state, constructors, and a mix of abstract and concrete methods.
Rule of thumb:
- Use an interface to define a capability that unrelated classes can share (
Comparable,Runnable). - Use an abstract class to share state and code among closely related classes.
An interface with exactly one abstract method is a functional interface and can be implemented with a lambda.
Interfaces as contracts
An interface lists what a type can do, not how. A class can implement many interfaces. Interface fields are implicitly public static final constants, and methods are public.
interface Payable { long amountPaise(); }
interface Refundable { void refund(); }
class Order implements Payable, Refundable {
public long amountPaise() { return 149_900; }
public void refund() { /* ... */ }
}Default, static and private methods
Since Java 8, interfaces can have default methods (so new methods don't break existing implementations) and static helper methods. Java 9 added private methods to share code between defaults.
interface Discountable {
long pricePaise();
default long priceAfter(int percent) { return round(pricePaise() * (100 - percent) / 100.0); }
static Discountable of(long paise) { return () -> paise; }
private long round(double v) { return Math.round(v); }
}When two defaults clash
If a class inherits the same default method from two interfaces, it must override it and can pick one with Interface.super.method(). A method from a superclass always wins over an interface default.
interface A { default String hi() { return "A"; } }
interface B { default String hi() { return "B"; } }
class C implements A, B {
@Override public String hi() { return A.super.hi() + B.super.hi(); }
}Functional interfaces
An interface with exactly one abstract method is functional and can be implemented with a lambda. @FunctionalInterface makes the compiler enforce that. Runnable, Comparator and everything in java.util.function are functional interfaces.
Abstract class or interface?
- Interface: a capability many unrelated classes can share; no instance state; a class can implement several.
- Abstract class: shared state and code for closely related classes; constructors; a class can extend only one.
Default to interfaces for APIs and dependencies (they're easy to mock and swap); reach for an abstract class to share implementation between siblings.
Sealed interfaces (Java 17)
A sealed interface lists exactly which types may implement it, so switches over it can be checked for completeness. Great for modelling a fixed set of cases, such as payment results.
sealed interface PaymentResult permits Paid, Failed, Pending {}
record Paid(String paymentId) implements PaymentResult {}
record Failed(String reason) implements PaymentResult {}
record Pending() implements PaymentResult {}Example
interface Notifier {
void send(String to, String msg);
default void sendAll(List<String> users, String msg) { // Java 8
users.forEach(u -> send(u, format(msg)));
}
private String format(String msg) { // Java 9
return "[JavaAtlas] " + msg;
}
static Notifier console() { // Java 8
return (to, msg) -> System.out.println(to + ": " + msg);
}
}
Notifier.console().sendAll(List.of("asha", "ravi"), "A new lesson is live");Common mistake
Trying to keep per-object state in an interface. Interface fields are static and final, so every implementation shares the same constant.
Under the hood
Default methods were added so the JDK could evolve interfaces like Collection (adding stream() and forEach) without breaking every existing implementation. Conflict rules: a class method always wins over an interface default; between two interfaces, the more specific one wins; otherwise you must override.
Check yourself
Since which version can interfaces have private methods?
How this connects
Know these first
Where this leads
Part of Java from zero.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.