Interfaces
"Can-do" relationships — describing capabilities a class promises to provide, independent of any class hierarchy
Inheritance models is-a ("a Circle is a Shape"). But many relationships in real code are more like can-do ("this thing can be compared," "this thing can be printed nicely," "this thing can be iterated over"). Java captures can-do with interfaces.
What is an interface?
An interface is a contract. It says: "any class that implements me promises to provide these methods." It does not say how — only what.
public interface Greeter {
String greet(String name);
}Any class that says implements Greeter must provide a method with
exactly that signature. The interface itself has no fields, no
constructor, and (traditionally) no method bodies.
Implementing an interface
Notice that say takes a Greeter — not a FormalGreeter or a
CasualGreeter. The method works with any current or future class
that implements Greeter. This is the same polymorphism we saw with
inheritance, but achieved without extends.
Interfaces vs abstract classes
You may be thinking: "this sounds like an abstract class." There is overlap, but the differences matter.
| abstract class | interface | |
|---|---|---|
| Models | is-a (identity) | can-do (capability) |
| Fields | Yes, any kind | Only public static final constants |
| Constructors | Yes | No |
| State | Yes (instance fields) | No |
| How many can a class have? | Extends one | Implements many |
| Code reuse | Strong — shared fields + methods | Limited (default methods only) |
The single most important difference: a class can implements
many interfaces but extends only one class.
That is why interfaces are perfect for capabilities: a BankAccount
can be Comparable, Serializable, and Loggable all at once,
without trying to inherit from three different parents.
The dashed arrows mean "implements."
A more realistic example: sorting anything
The Java standard library defines:
public interface Comparable<T> {
int compareTo(T other);
}Any class that implements Comparable can be sorted by
Collections.sort or Arrays.sort. The library has no idea what
your class is — it just trusts the contract.
Arrays.sort was written years before your Book class existed.
It works because Book honors the Comparable contract.
Default methods
Since Java 8, interfaces may carry default methods — methods with a body that subclasses inherit unless they override. This lets interfaces evolve over time without breaking existing implementations.
Use default methods sparingly. Their main job is backwards compatibility, not "everyone gets free behavior."
Designing with interfaces: depend on capabilities, not classes
A subtle but vital design rule: prefer interface types in method
parameters and return types. Saying void process(List<Order> orders) is better than void process(ArrayList<Order> orders).
Why? Because callers may have an ArrayList, a LinkedList, or
anything else that implements List. Asking only for the
capability you actually need gives callers freedom and gives you
the right to change your storage later.
The method process doesn't care which arrow the data came down. It
only cares that it can call List methods on the parameter.
What is the most fundamental difference between an abstract class and an interface?
Abstract classes are faster
A class can implement many interfaces but extend only one class, so interfaces are the right way to mix in multiple independent capabilities
Interfaces support fields, abstract classes don't
Interfaces don't allow @Override
Why is it good practice to declare a parameter type as List<T> rather than ArrayList<T>?
It's shorter to type
ArrayList is deprecated
You ask only for the capability you actually need, so callers can pass any List implementation and you can change your own storage later
The compiler refuses concrete types in parameters
A small challenge
Define an interface Printable with one method String toReport().
Then define two classes that both implement Printable:
Invoicewith a constructorInvoice(int id, int totalCents)andtoReport()returning"Invoice #" + id + ": " + totalCents + "c".Greetingwith a constructorGreeting(String who)andtoReport()returning"Hi, " + who + "!".
Main.java is provided. Expected output (exact):
Invoice #7: 1299c
Hi, Ada!
Interfaces are how grown-up Java programs are organized. They draw clean lines between what a piece of code needs and what concrete class happens to provide it. The next chapter zooms out from classes to ask: how does a Java program actually execute?