Dataslope logoDataslope

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

Code Block
Java 8 (Update 492)

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 classinterface
Modelsis-a (identity)can-do (capability)
FieldsYes, any kindOnly public static final constants
ConstructorsYesNo
StateYes (instance fields)No
How many can a class have?Extends oneImplements many
Code reuseStrong — shared fields + methodsLimited (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.

Code Block
Java 8 (Update 492)

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.

Code Block
Java 8 (Update 492)

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.

QuestionSelect one

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

QuestionSelect one

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

Challenge
Java 8 (Update 492)
A printable hierarchy

Define an interface Printable with one method String toReport().

Then define two classes that both implement Printable:

  • Invoice with a constructor Invoice(int id, int totalCents) and toReport() returning "Invoice #" + id + ": " + totalCents + "c".
  • Greeting with a constructor Greeting(String who) and toReport() 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?

On this page