Java Interfaces
Define contracts in Java with interfaces — abstract methods, default methods, and multiple inheritance of type.
An interface is a contract: a named set of operations that any implementing class promises to provide. Interfaces have no instance state, no constructors, and (with one exception covered next chapter) no method bodies. They describe what a type can do, leaving every how to the implementations.
Interfaces are Java's answer to multiple inheritance. A class extends exactly one class but can implement any number of interfaces — letting you mix in a Comparable, an AutoCloseable, and an Iterable on the same type without ambiguity.
Declaring an interface
Use interface instead of class:
public interface Shape {
double area(); // implicitly public abstract
double perimeter();
}Method declarations in an interface are implicitly public abstract. You can write those modifiers, but most style guides drop them as noise — they're redundant.
Implementing an interface
A class declares it with implements. The class must supply a body for every method the interface declares:
public class Circle implements Shape {
private final double r;
public Circle(double r) { this.r = r; }
@Override public double area() { return Math.PI * r * r; }
@Override public double perimeter() { return 2 * Math.PI * r; }
}If a class implements an interface but doesn't provide all the methods, the class must be declared abstract — same rule as with abstract classes.
You can also implement many interfaces at once:
public class Money implements Comparable<Money>, java.io.Serializable {
private final long cents;
public Money(long cents) { this.cents = cents; }
public int compareTo(Money other) { return Long.compare(this.cents, other.cents); }
}This is "multiple inheritance of type" — Money is both a Comparable<Money> and a Serializable. Code that wants either can take a Money.
Programming to an interface
The point of interfaces is to write code against the contract, not the implementation:
public double sumAreas(List<Shape> shapes) {
double sum = 0;
for (Shape s : shapes) sum += s.area();
return sum;
}sumAreas doesn't know or care about Circle. Add Square implements Shape, Triangle implements Shape, and the function works on lists of them too — no changes.
The standard library is built on this pattern. You almost always declare a variable of an interface type and instantiate a concrete one:
List<String> names = new ArrayList<>(); // List, not ArrayList
Map<String, Integer> counts = new HashMap<>(); // Map, not HashMapIf you later switch to LinkedList or LinkedHashMap, only the new line changes.
Constants on interfaces
Every field declared in an interface is implicitly public static final — a constant. You typically don't add constants to interfaces (it's regarded as bad style — the Constant Interface Antipattern), but the syntax exists:
public interface Color {
String DEFAULT = "black"; // implicitly public static final
}If you need constants, prefer an enum or a plain final class with public static final fields.
Interfaces can extend interfaces
An interface can extend other interfaces — even multiple ones at once:
public interface Readable { String read(); }
public interface Writable { void write(String s); }
public interface ReadWrite extends Readable, Writable { }Now any class that implements ReadWrite has to provide both read() and write(). There's no class extends / interface implements distinction here — interfaces just extend interfaces with extends.
Default and static methods (preview)
Since Java 8, interfaces can have default methods (bodies provided via the default keyword) and static methods. They let you add behavior to an interface without breaking every existing implementor. The full treatment is the next chapter, default methods:
public interface Shape {
double area();
// Default method — implementors get this for free.
default String describe() {
return getClass().getSimpleName() + " area=" + area();
}
// Static factory on the interface itself.
static Shape unitCircle() { return new Circle(1); }
}Marker interfaces
A marker interface declares no methods. It exists purely as a label that runtime code can check for:
public interface Cacheable { } // no methods
public class Snapshot implements Cacheable { ... }Then somewhere else: if (obj instanceof Cacheable) { ... }. Modern Java prefers annotations for this kind of metadata (@Cacheable instead of implements Cacheable), but Serializable, Cloneable, and RandomAccess are well-known marker interfaces in the standard library.
Choosing between an interface and an abstract class
The decision tree:
- Do subclasses need to share state or shared method implementations? If yes, you probably want an abstract class — interfaces can't hold instance state.
- Do you want a type that several otherwise-unrelated classes can satisfy? If yes, an interface — a class can implement many interfaces but extend only one class.
- Will the contract grow over time? Interfaces evolve more carefully — adding an abstract method to an interface breaks every implementor unless you make it a
defaultmethod. Abstract classes can add a concrete method without breaking anyone.
In most real codebases, interfaces win for type contracts and abstract classes appear behind the scenes when several implementations share infrastructure.
A worked example
What's next
Interfaces used to be pure contracts — no method bodies at all. Since Java 8 that's relaxed: interfaces can provide default methods, static methods, and even private helper methods. The next chapter is a tour of those additions. Continue to default methods.
Practice
What is the practical reason Java does not allow a class to extend more than one class but lets a class implement many interfaces?