Interfaces
An interface is a contract: a set of method signatures that a class promises to implement, without necessarily saying how. You declare one with the interface keyword, and a class agrees to the contract using implements.
A basic interface
interface Payable {
double calculatePay(); // no body — just a signature
}
class Employee implements Payable {
private final double hoursWorked;
private final double hourlyRate;
Employee(double hoursWorked, double hourlyRate) {
this.hoursWorked = hoursWorked;
this.hourlyRate = hourlyRate;
}
@Override
public double calculatePay() {
return hoursWorked * hourlyRate;
}
}Multiple interfaces — Java's answer to multiple inheritance
As covered on the Inheritance page, a Java class can only extend one other class — Java deliberately does not support multiple class inheritance. Interfaces sidestep that limitation: a single class can implements as many interfaces as it needs, so a class can promise to support several unrelated capabilities at once.
Implementing multiple interfaces
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("The duck flies.");
}
@Override
public void swim() {
System.out.println("The duck swims.");
}
}Default methods (Java 8+)
Originally, every method in an interface had to be abstract. Since Java 8, an interface can provide a default method — a method with an actual body, marked with the default keyword. Implementing classes inherit this behavior automatically and only need to override it if they want different behavior.
A default method
interface Greeter {
String name();
// default method — has a real implementation
default void greet() {
System.out.println("Hello, " + name() + "!");
}
}
class Person implements Greeter {
private final String personName;
Person(String personName) {
this.personName = personName;
}
@Override
public String name() {
return personName;
}
// greet() is inherited for free — no override needed
}
public class Main {
public static void main(String[] args) {
new Person("Ava").greet(); // Hello, Ava!
}
}Default methods were introduced specifically to let library authors add new methods to existing interfaces (like the forEach method added to Collection) without breaking every class that already implements that interface.
Static methods on interfaces
Interfaces can also declare static methods, called directly on the interface name rather than on an implementing instance — useful for factory or helper methods related to the interface.
A static interface method
interface MathOperation {
int apply(int a, int b);
static MathOperation addition() {
return (a, b) -> a + b;
}
}
// Usage: MathOperation op = MathOperation.addition();Abstract classes vs. interfaces
Abstract class | Interface | |
|---|---|---|
Implementation | A class | A class |
Constructors | Allowed | Not allowed |
Instance fields (state) | Allowed, any access level | Only |
Method bodies | Any method can be concrete | Only |
When to choose | Related types sharing real state/behavior | Unrelated types sharing a capability/contract |
Interfaces declare a contract of method signatures a class agrees to implement.
A class can implement multiple interfaces — Java's alternative to multiple inheritance.
Default methods (Java 8+) let interfaces provide real method bodies.
Static methods live on the interface itself, not on implementing instances.