Learning goals
Choose between abstract classes and interfaces, implement contracts with implements, use default and static interface methods, and design APIs that stay flexible as requirements evolve.
Abstract classes
Cannot be instantiated; may mix abstract and concrete members:
public abstract class Payment {
protected final String id;
protected Payment(String id) {
this.id = id;
}
public abstract void capture(); // subclass must implement
public void log() {
System.out.println("Payment " + id);
}
}
public class CardPayment extends Payment {
public CardPayment(String id) {
super(id);
}
@Override
public void capture() {
System.out.println("Charging card " + id);
}
}
Use abstract classes when subclasses share state and implementation (protected fields, concrete helpers).
Interfaces
Pure contract—methods without implementation (historically):
public interface Notifier {
void send(String message);
}
public class SmsNotifier implements Notifier {
@Override
public void send(String message) {
System.out.println("SMS: " + message);
}
}
A class extends one superclass, implements zero or more interfaces:
public class EmailSmsNotifier implements Notifier, Auditable {
// implement both interfaces
}
Default and static methods (JDK 8+)
Evolve interfaces without breaking implementors:
public interface Notifier {
void send(String message);
default void sendUrgent(String message) {
send("[URGENT] " + message);
}
static Notifier noop() {
return message -> { };
}
}
Default — instance method with body; inherited unless overridden.
Static — called on interface (Notifier.noop()), not on instance.
Private interface methods (JDK 9+)
Share code between defaults without exposing helpers:
public interface Parser {
default int parseInt(String s) {
return Integer.parseInt(trim(s));
}
private String trim(String s) {
return s.strip();
}
}
Abstract class vs interface
| Abstract class | Interface | |
|---|---|---|
| Inheritance | Single extends |
Multiple implements |
| State | Can hold fields | Only public static final constants traditionally; records/sealed patterns evolve |
| Constructor | Yes | No instance fields to construct |
| Use when | Shared base behavior + state | Capability / role (“Can fly”, “Serializable”) |
Modern style: prefer interfaces for API boundaries; abstract class when template method pattern needs shared non-public state.
Functional interfaces (JDK 8+)
Single abstract method (SAM) — lambda target:
@FunctionalInterface
public interface Transformer<T, R> {
R apply(T input);
}
Transformer<String, Integer> len = s -> s.length();
System.out.println(len.apply("hi")); // 2
@FunctionalInterface is optional but documents intent; compiler enforces one abstract method.
Template method pattern
Abstract class defines skeleton; subclasses fill steps:
public abstract class DataImporter {
public final void importAll() { // final prevents override of flow
open();
read();
close();
}
protected abstract void read();
protected void open() { System.out.println("Opening"); }
protected void close() { System.out.println("Closing"); }
}
Marker interfaces (legacy)
Empty interface (Serializable) tags capability. Prefer annotations or explicit methods today unless interfacing with JDK APIs that require markers.
Common mistakes
- Implementing interface but wrong method signature — not an override; compile error if
@Overrideused. - Diamond conflict — two interfaces with same default method; class must override to resolve.
- Fat interfaces — violate Interface Segregation; split
WorkerintoRunnable,Stoppable. - Abstract class for only constants — use interface or final class with private constructor.
- Public fields in interfaces — constants are implicitly
public static final; don’t misuse as data bag.
Practice checkpoint
-
Define
Drawablewithvoid draw()and implement inCircle.- Answer: interface +
@Override void draw().
- Answer: interface +
-
Can a class extend
Paymentand implementAuditable?- Answer: Yes—one extends, many implements.
-
What happens if two interfaces define same default method?
- Answer: Implementing class must override unless one inherits from the other.
-
When use abstract class over interface for
Animal/Dog?- Answer: Shared fields (
name,age) and partial implementation in base.
- Answer: Shared fields (
Interview angles
- “Interface vs abstract class JDK 8+?” — Interfaces can have defaults/static; still single inheritance for classes.
- “Why default methods?” — Backward-compatible library evolution (e.g.,
Collection.stream()). - “Can interface have constructor?” — No.