Java Tutorial · Object-Oriented Java · Lesson 22 of 37
Java Abstract Classes and Interfaces
Define contracts with interfaces and partial implementations with abstract classes.
Interfaces
An interface defines what a class can do. Classes implements it and must provide every abstract method. Interfaces can also have default methods with a body:
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Notifier> channels = List.of(new EmailNotifier(), new SmsNotifier());
for (Notifier n : channels) {
System.out.println(n.send("Your order shipped"));
System.out.println(n.sendUrgent("Payment failed"));
}
}
}
interface Notifier {
String send(String message);
default String sendUrgent(String message) {
return send("URGENT: " + message);
}
}
class EmailNotifier implements Notifier {
public String send(String message) { return "Email -> " + message; }
}
class SmsNotifier implements Notifier {
public String send(String message) { return "SMS -> " + message; }
}
Output
Email -> Your order shipped Email -> URGENT: Payment failed SMS -> Your order shipped SMS -> URGENT: Payment failed
Run this on your computer — see “Get Started” for setup.
Abstract classes
An abstract class can't be instantiated. It can hold fields, constructors and concrete methods, plus abstract methods that subclasses must implement:
public class Main {
public static void main(String[] args) {
Shape[] shapes = {new Circle(1), new Rectangle(2, 3)};
for (Shape s : shapes) {
System.out.println(s.describe());
}
}
}
abstract class Shape {
abstract double area();
String describe() {
return String.format("%s with area %.2f", getClass().getSimpleName(), area());
}
}
class Circle extends Shape {
private final double r;
Circle(double r) { this.r = r; }
double area() { return Math.PI * r * r; }
}
class Rectangle extends Shape {
private final double w, h;
Rectangle(double w, double h) { this.w = w; this.h = h; }
double area() { return w * h; }
}
Output
Circle with area 3.14 Rectangle with area 6.00
Run this on your computer — see “Get Started” for setup.
Sealed types (Java 17+)
sealed restricts which classes may implement an interface — the compiler then knows every case, which works beautifully with pattern-matching switch.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Payment> payments = List.of(new Card("4242"), new BankTransfer("DE89..."), new Cash());
for (Payment p : payments) {
String text = switch (p) {
case Card c -> "card ending " + c.last4();
case BankTransfer b -> "transfer from " + b.iban();
case Cash c -> "cash";
}; // no default needed: the compiler knows all cases
System.out.println(text);
}
}
}
sealed interface Payment permits Card, BankTransfer, Cash {}
record Card(String last4) implements Payment {}
record BankTransfer(String iban) implements Payment {}
record Cash() implements Payment {}
Output
card ending 4242 transfer from DE89... cash
Run this on your computer — see “Get Started” for setup.
Test yourself
Which keyword does a class use to implement an interface?
extendsimplementsusesinherits
Show answer
Answer: implements