Skip to content
Theory · Interfaces, enums and records · lesson 1 of 8

Interfaces

What you'll learn

What you'll learn:

  • describe an ability with an interface and implement it in classes with implements;
  • explain when a default method runs and choose between an interface and an abstract class;
  • create a fixed set of values with enum and handle it in a switch;
  • describe immutable data in one record line and compare records with equals.

Picture a job ad: "Courier wanted. Must be able to deliver a parcel." The ad does not say who the courier must be. A student on a bicycle can take the job, so can a van driver, and even a drone: anyone who can do what is listed fits.

The person who sends the parcel does not care who comes for it either. They tell the courier "deliver", and how to deliver is up to the courier.

Why does a program need this? In the previous theme, the common buttons of classes came from a parent. But a cyclist and a drone share nothing except the ability to deliver: no common fields, no common ancestor. Besides, a class can have only one parent. For an ability that quite different classes can have, Java has the interface:

JAVA
public class Main {
    public static void main(String[] args) {
        Courier c = new Cyclist();
        c.deliver("book"); // Cyclist brings book
    }
}

interface Courier { void deliver(String parcel); }

class Cyclist implements Courier {
    public void deliver(String parcel) {
        System.out.println("Cyclist brings " + parcel);
    }
}

Let's go through the program step by step:

  1. interface Courier is the job ad. Its braces hold only the deliver header, with a semicolon instead of a body: the interface says what to do, not how.
  2. class Cyclist implements Courier means the cyclist takes this job. The word implements promises that the class has every method of the interface.
  3. Inside Cyclist, the deliver method is written in full, with a body.
  4. Courier c = new Cyclist(); declares a variable of type Courier and puts a reference to a Cyclist object into it.
  5. c.deliver("book") runs the cyclist's method and prints Cyclist brings book.

Interfaces and implements

An interface is a type that lists methods but does not write their bodies. You have already met methods without a body in abstract classes: in an interface they are abstract too. A class implements an interface when it writes each of its methods, and it says so with the word implements.

What matters about an interface:

  • a method without a body in an interface is always public, even when the word is not written, so the class declares it public too;
  • you cannot create an object of an interface: for new Courier() the compiler answers Courier is abstract; cannot be instantiated;
  • the compiler checks that the class has written every method of the interface, and if even one is missing, the program does not compile.

Here is what javac says about a Cyclist class that forgot the deliver method:

TEXT
error: Cyclist is not abstract and does not override abstract method deliver(String) in Courier

The start of the message, is not abstract, is no accident: an abstract class from the previous theme may leave a method to its subclasses. An ordinary class must write everything.

You can put @Override above such methods, as in the previous theme. Then the compiler checks that a method with that header really exists in the interface.

Several interfaces

One person can work both as a courier and as a photographer. In the same way, a class can implement any number of interfaces: you list them after implements, separated by commas. A drone can both deliver and take pictures from above:

JAVA
interface Camera { String photo(); }

class Drone implements Courier, Camera {
    public void deliver(String parcel) {
        System.out.println("Drone drops " + parcel);
    }

    public String photo() {
        return "view from above";
    }
}

A class still has only one parent through extends, and as many interfaces as it needs. When there are both, extends comes first and implements second: class Van extends Vehicle implements Courier, Camera.

Interviewers like to ask this: does Java have multiple inheritance? The answer: a class extends only one class but can implement several interfaces.

A variable of an interface type

The variable Courier c works like the universal remote from the previous theme: its type decides which buttons exist, and the object decides what they do. A variable of type Courier can hold an object of any class that implements Courier:

JAVA
Courier first = new Cyclist();
Courier second = new Drone();
first.deliver("pizza");  // Cyclist brings pizza
second.deliver("pizza"); // Drone drops pizza

Let's go through it line by line:

  1. first holds a cyclist and second holds a drone, but both variables have the same type: Courier.
  2. first.deliver("pizza") runs the method of the Cyclist class.
  3. second.deliver("pizza") is written the same way, but another object does the work: the method of the Drone class runs.

The Courier remote has one button, deliver. That is why second.photo() does not compile, even though second holds a drone: the compiler answers cannot find symbol. To take a photo, you need a variable of type Camera.

Here the job-ad picture is not exact. A real employer may hire someone who can do only half the work, hoping they will learn. The compiler does not do that: a class gets the job only if it can do everything listed.

Common mistake

The class forgot to write public before an interface method:

JAVA
class Cyclist implements Courier {
    void deliver(String parcel) { // ✗
        System.out.println("Cyclist brings " + parcel);
    }
}
TEXT
error: deliver(String) in Cyclist cannot implement deliver(String) in Courier

The program does not compile. The interface method is public, while a method with no modifier is seen only by the classes of its package. A class cannot narrow the access the interface promised. javac explains this on the next line: attempting to assign weaker access privileges; was public. Add public before void deliver.

Key points

  • An interface lists methods without bodies, and a class implements it with implements and writes each method itself, as public.
  • If a class has not written even one method of the interface, the program does not compile.
  • A class has one parent through extends, but it can implement any number of interfaces.
  • A variable of an interface type takes an object of any class that implements it and lets you call only the interface's methods.