Learn Java

Lesson 24Phase 3: Abstraction and design

Interfaces

A pure contract of behavior, implementing one, and why a class can satisfy many at once.

By Updated 55 min

  • interface
  • implements
  • contract
  • multiple interfaces
  • default methods
  • constants

You can already make one variable stand in for many kinds of object, and you can make a parent class force its children to write certain methods. The next step is to describe an ability on its own, apart from any family of classes: whatever this thing is, it can be drawn. A promise like that is called an interface. Java's own library is full of them, and by the end of this lesson you will be writing your own.

By the end of this lesson
  • Say what an interface is in one plain sentence: a named set of methods that a class promises to provide.
  • Write a class that implements an interface and provides every method it promised.
  • Hold different classes in one interface-typed variable or array, and drive them all with one loop.
  • Give one class several abilities by implementing more than one interface, alongside a parent class.
  • Use constants and default methods in an interface, and say what an interface still cannot hold.
From before
This builds straight on polymorphism (one general type, many runtime forms) and abstract classes(a type that forces its children to write certain methods). An interface takes the “you must write this method” idea from abstract classes and frees it from any single family tree.

A capability that crosses family lines#

Suppose you are building a small drawing program. It paints shapes on a screen, but it also paints other things: a button, a chart, a line of text. What all of these share is that the program can ask each one to draw itself. They share a capability, drawing, but not a family. A button is not a kind of circle, and a chart is not a kind of text. No sensible parent class has a circle, a button and a chart as its children.

Inheritance alone leaves you stuck. Inheritance says “is a kind of”, and these things are not kinds of each other. What you want to say is looser: “each of these can be drawn, however differently each one does it”. You need a way to name a capability by itself, with no family attached.

Key idea

Inheritance answers “what is this thing?”. An interface answers “what can this thing do?”. Many designs need the second question answered more than the first.

An interface is a contract of behavior#

In its simplest form, an interface is a list of methods, each with a name, parameters and a return type but no body. It holds no fields of data. It says what must be possible, never how it is done. Read this one out loud:

Drawable.java
1public class Main {
2 public static void main(String[] args) {
3 System.out.println("An interface defines what, not how.");
4 }
5}
6
7interface Drawable {
8 void draw();
9}
Prints
›An interface defines what, not how.

Drawable says one thing: any class that claims to be drawable must have a method draw() that takes nothing and returns nothing. After draw() there is no body, only a semicolon. The program does nothing with Drawable yet; it shows that the interface compiles. The next section puts it to work.

A signature is a method without its body
You met signatures in overriding and super: a method's name plus its parameter types. An interface is built almost entirely out of them. A method line that ends in ; instead of { ... } is a promise of a method. The class that implements the interface is where the body lives.
Key idea

An interface is a promise. It names what a class must be able to do, and says nothing about how the class does it.

Keeping the promise with implements#

A promise is only worth something when someone keeps it. A class keeps an interface's promise with the keyword implements. Inheritance uses extendsto say “is a kind of”; a class uses implements to say “can do”. When a class says it implements Drawable, the compiler makes it provide a real draw() with a body, or the class does not compile. Here is a Circle that keeps the promise.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Circle c = new Circle();
4 c.draw();
5 }
6}
7
8interface Drawable {
9 void draw();
10}
11
12class Circle implements Drawable {
13 public void draw() {
14 System.out.println("Drawing a circle");
15 }
16}
Prints
›Drawing a circle

It prints Drawing a circle. Circle declared implements Drawable, so it had to define draw(), and it did. Notice that the method is marked public. Every method an interface declares is public, because the point of an interface is to advertise a capability to everyone, so the class that provides the method must make it public too.

Leave out the promised method and it will not compile
If Circle said implements Drawable but never wrote draw(), javac would stop with Circle is not abstract and does not override abstract method draw() in Drawable. It is the message you met with abstract classes, because a method in an interface is abstract unless it says otherwise. The moment a class claims a capability, the compiler holds it to the claim.
Quick check
Circle implements Drawable, but its method is written void draw() { ... }, without public. What happens?

Now add a second, unrelated class. A Square is not a kind of Circle and shares no parent with it, yet both can be drawn. Each one writes draw() its own way.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Circle c = new Circle();
4 Square s = new Square();
5 c.draw();
6 s.draw();
7 }
8}
9
10interface Drawable {
11 void draw();
12}
13
14class Circle implements Drawable {
15 public void draw() {
16 System.out.println("Drawing a circle");
17 }
18}
19
20class Square implements Drawable {
21 public void draw() {
22 System.out.println("Drawing a square");
23 }
24}
Prints
›Drawing a circle
›Drawing a square

This prints Drawing a circle, then Drawing a square. Two classes with nothing else in common keep the same promise, each in its own way. That shared promise lets you treat them as one kind of thing, even though they share no family.

Polymorphism through the interface type#

Because both Circle and Square implement Drawable, a variable typed Drawable can hold either one. This is the upcasting you saw with polymorphism, except that the general type is now an interface instead of a parent class. The program can hold a thing by its capability and set aside what it actually is.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Drawable d = new Circle();
4 d.draw();
5
6 d = new Square();
7 d.draw();
8 }
9}
10
11interface Drawable {
12 void draw();
13}
14
15class Circle implements Drawable {
16 public void draw() {
17 System.out.println("Drawing a circle");
18 }
19}
20
21class Square implements Drawable {
22 public void draw() {
23 System.out.println("Drawing a square");
24 }
25}
Prints
›Drawing a circle
›Drawing a square

Step through it and watch d in the memory view. It is typed Drawable. First it points at Circle #1, so d.draw() prints Drawing a circle. Then the same variable is pointed at Square #1, and d.draw() prints Drawing a square. The declared type, Drawable, decided what you were allowed to call: just draw(). The real object decided which version ran. That is dynamic dispatch, working exactly as it did for classes.

Put the lines in orderPlayer.java
Put the lines in order: a Playable interface, a Song that implements it, and a main that plays the song through a Playable variable. The program prints Playing Clocks.

Tap a line, then tap where it should go. Or use the arrows.

Now put the whole idea in one loop. An array typed Drawable[] can hold circles and squares side by side, and one line draws them all.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Drawable[] shapes = { new Circle(), new Square(), new Circle() };
4
5 for (int i = 0; i < shapes.length; i++) {
6 shapes[i].draw();
7 }
8 }
9}
10
11interface Drawable {
12 void draw();
13}
14
15class Circle implements Drawable {
16 public void draw() {
17 System.out.println("Drawing a circle");
18 }
19}
20
21class Square implements Drawable {
22 public void draw() {
23 System.out.println("Drawing a square");
24 }
25}
Prints
›Drawing a circle
›Drawing a square
›Drawing a circle

The output is Drawing a circle, Drawing a square, Drawing a circle. The loop never mentions Circle or Square. It speaks only to the capability, Drawable, and each object answers in its own way. Add a Triangle that implements Drawable, put a new Triangle() in the array, and the loop draws it too, without a single change to the loop.

Key idea

Code written against an interface does not care what the real objects are, only that they keep the promise. You add new kinds by writing new classes, not by editing the code that uses them.

ExerciseBasket.java
A shopping basket holds books and a coffee, all of them Priced. Finish main so it adds up the price of everything in the basket. Call the price through the interface: the loop should not need to know which items are books.
Coming from Python?
Python calls x.draw() on any object that happens to have a draw method, and finds out at the moment of the call whether it does. Java asks you to write the promise down as an interface, so the compiler can check every drawable thing before the program runs.

Many capabilities at once#

A class can extend only one parent class, but it can implement as many interfaces as it likes, listed with commas. That fits what each one means. A thing has one identity, one answer to “what is it?”, but it can have many abilities.

Picture an on-screen button. It can be drawn, and it can be clicked: two separate capabilities. Write one interface for each, and a Button class promises both.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Button b = new Button();
4 b.draw();
5 b.click();
6 }
7}
8
9interface Drawable {
10 void draw();
11}
12
13interface Clickable {
14 void click();
15}
16
17class Button implements Drawable, Clickable {
18 public void draw() {
19 System.out.println("Drawing a button");
20 }
21 public void click() {
22 System.out.println("Button clicked");
23 }
24}
Prints
›Drawing a button
›Button clicked

The output is Drawing a button, then Button clicked. Button said implements Drawable, Clickable, so the compiler required both draw() and click(), and the class provided both. A plain Circle might implement only Drawable, a checkbox might implement both, and a sound effect might implement only some Playable interface. Each class takes on exactly the capabilities it has.

Quick check
With Drawable d = new Button();, where Button implements both Drawable and Clickable, which call compiles?

Asking an object what it can do

To reach click() from a Drawable variable, ask the object first. instanceof works with interfaces just as it does with classes. Every item on this screen can be drawn, but only some can also be clicked.

Screen.java
1public class Main {
2 public static void main(String[] args) {
3 Drawable[] screen = { new Circle(), new Button() };
4 for (Drawable d : screen) {
5 d.draw();
6 if (d instanceof Clickable) {
7 Clickable c = (Clickable) d;
8 c.click();
9 }
10 }
11 }
12}
13
14interface Drawable {
15 void draw();
16}
17
18interface Clickable {
19 void click();
20}
21
22class Circle implements Drawable {
23 public void draw() {
24 System.out.println("Drawing a circle");
25 }
26}
27
28class Button implements Drawable, Clickable {
29 public void draw() {
30 System.out.println("Drawing a button");
31 }
32
33 public void click() {
34 System.out.println("Button clicked");
35 }
36}
Prints
›Drawing a circle
›Drawing a button
›Button clicked

It prints Drawing a circle, Drawing a button and Button clicked. The circle fails the instanceof Clickable test, so it is only drawn. The button passes, so the loop casts it to Clickable and clicks it: the same check-then-cast pattern you used for downcasting in polymorphism.

A parent class and interfaces together

A class can do both at once: extend one class and implement any number of interfaces. The extends part comes first. A duck is a kind of bird, so it extends Bird, and it can also swim and fly.

Pond.java
1public class Main {
2 public static void main(String[] args) {
3 Duck d = new Duck("Pip");
4 d.introduce();
5 d.swim();
6 d.fly();
7 }
8}
9
10class Bird {
11 String name;
12
13 Bird(String name) {
14 this.name = name;
15 }
16
17 void introduce() {
18 System.out.println("I am " + name);
19 }
20}
21
22interface Swimmer {
23 void swim();
24}
25
26interface Flyer {
27 void fly();
28}
29
30class Duck extends Bird implements Swimmer, Flyer {
31 Duck(String name) {
32 super(name);
33 }
34
35 public void swim() {
36 System.out.println(name + " paddles across the pond");
37 }
38
39 public void fly() {
40 System.out.println(name + " flaps off");
41 }
42}
Prints
›I am Pip
›Pip paddles across the pond
›Pip flaps off

It prints I am Pip, Pip paddles across the pond and Pip flaps off. introduce() and the name field come from Bird, the one parent. swim() and fly() are the duck's answers to two promises. A Duck can now sit in a Bird variable, a Swimmer variable or a Flyer variable.

Quick check
Bird is a class, and Swimmer and Flyer are interfaces. Which class header compiles?
Inheritance (extends)
Interfaces (implements)
Says “is a kind of”. One identity.
Says “is able to”. A capability.
A class may extend only one parent.
A class may implement many interfaces.
Can pass down fields and finished methods.
Mostly promises method signatures, and holds no per-object data.
Best for a true family tree (a Dog is an Animal).
Best for an ability shared by unrelated classes.
ExerciseLamp.java
The lamp can be switched on and off, but it cannot be dimmed yet. Make Lamp implement Dimmable as well, so that dimTo(40) prints Lamp at 40%. Then, in main, dim the lamp to 40 and turn it off.

Constants and default methods#

Two more features finish the picture. You will meet both in real code, so it is worth an honest look at each.

Constants in an interface

An interface can hold a named constant, a value that never changes and that every implementing class shares. A field written in an interface is automatically public (visible everywhere), static (one copy for the whole interface, not one per object) and final (set once, never changed). The best constants are part of the promise itself. Here, anything Adjustable promises to keep its level at or below MAX_LEVEL.

Main.java
1public class Main {
2 public static void main(String[] args) {
3 Speaker s = new Speaker();
4 s.setVolume(7);
5 s.setVolume(15);
6 System.out.println("Loudest allowed: " + Adjustable.MAX_LEVEL);
7 }
8}
9
10interface Adjustable {
11 int MAX_LEVEL = 10;
12
13 void setVolume(int level);
14}
15
16class Speaker implements Adjustable {
17 int level;
18
19 public void setVolume(int level) {
20 this.level = Math.min(level, MAX_LEVEL);
21 System.out.println("Volume " + this.level);
22 }
23}
Prints
›Volume 7
›Volume 10
›Loudest allowed: 10

It prints Volume 7, then Volume 10, because Math.min caps the 15 at the maximum, then Loudest allowed: 10. Inside Speaker, the class can write plain MAX_LEVEL, since it implements the interface. Anywhere else you read it through the interface's name, Adjustable.MAX_LEVEL. Because it is final, any attempt to give it a new value is refused.

More on static and final later
static (members that belong to the type, not to any object) and final (values that cannot change) have a life well beyond interfaces. They get a lesson of their own, static and final. Here you only need the one-line meanings above.

Default methods

Until Java 8, an interface could only hold methods without bodies. Java 8 added the default method: a method with a real body, marked with the keyword default. Every class that implements the interface gets the method for free, and may keep it or replace it. Default methods exist so that an interface can gain a new method without breaking the classes that already implement it. When Java 8 gave the List interface a new sort method, as a default, every list class written before then got it at once.

Describe.java
1public class Main {
2 public static void main(String[] args) {
3 Circle c = new Circle();
4 c.draw();
5 c.describe();
6 }
7}
8
9interface Drawable {
10 void draw();
11
12 default void describe() {
13 System.out.println("Describing: I am a drawable thing.");
14 }
15}
16
17class Circle implements Drawable {
18 public void draw() {
19 System.out.println("Drawing a circle");
20 }
21}
Prints
›Drawing a circle
›Describing: I am a drawable thing.

Circle wrote only draw(), yet it can call describe(), because the interface supplies a default body. A default method can also call the interface's other methods, even the ones without bodies, and a class can replace a default with its own version. Decide what this prints.

Predict the outputGreeters.java
1public class Main {
2 public static void main(String[] args) {
3 Greeter[] greeters = { new Robot(), new Pirate() };
4 for (Greeter g : greeters) {
5 g.greet("Sam");
6 }
7 }
8}
9
10interface Greeter {
11 String name();
12
13 default void greet(String who) {
14 System.out.println("Hello " + who + ", I am " + name());
15 }
16}
17
18class Robot implements Greeter {
19 public String name() {
20 return "Robot";
21 }
22}
23
24class Pirate implements Greeter {
25 public String name() {
26 return "Pirate";
27 }
28
29 public void greet(String who) {
30 System.out.println("Ahoy " + who + "!");
31 }
32}

Robot keeps the default greet; Pirate writes its own. What are the two lines?

It prints Hello Sam, I am Robot, then Ahoy Sam!. Robot keeps the default greet, which calls name(), and name()runs the robot's own version: the same template idea you met with abstract classes. Pirate overrides greet, so its own version runs and the default is never used.

An interface still holds no per-object data
A default method has a body, but the interface still has no fields holding the data of individual objects. There is no “the interface's own volume” the way a class has a field per object; the constant above is one fixed value shared by all. If you find yourself wanting per-object data inside the contract, you want a class.

What an interface can hold

Since Java 8 an interface can also have staticmethods, called on the interface's name the way you call Math.max, and since Java 9 it can have private methods, helpers that its default methods share and that no one outside can see. The table sums up what can go inside.

MemberExampleWhat it means
Abstract methodvoid draw();Public and bodiless. Every concrete class that implements the interface must write it.
Constantint MAX_LEVEL = 10;Always public static final: one shared value that never changes.
Default method (Java 8)default void describe() { ... }A body that implementing classes inherit and may override.
Static method (Java 8)static Shape unitSquare() { ... }Belongs to the interface itself, called as Shape.unitSquare().
Private method (Java 9)private String label() { ... }A helper for the default and static methods, hidden from everyone else.
Not allowedfields per object, constructorsAn interface keeps no data per object, and you cannot build one with new.
Quick check
Which of these can an interface not contain?

Interfaces you have already used#

Java's library is built on interfaces, and you have been using some without seeing their names. String and StringBuilder are unrelated classes, yet both implement an interface called CharSequence, a readable sequence of characters, which promises length() and charAt() among other methods. So one CharSequence variable can hold either.

Chars.java
1public class Main {
2 public static void main(String[] args) {
3 CharSequence text = "hello";
4 System.out.println(text.length() + " characters, first is " + text.charAt(0));
5
6 text = new StringBuilder("builder");
7 System.out.println(text.length() + " characters, first is " + text.charAt(0));
8 }
9}
Prints
›5 characters, first is h
›7 characters, first is b

It prints 5 characters, first is h, then 7 characters, first is b. There are more. The compareTo method from strings is how String keeps its promise to an interface called Comparable, which Java's sorting relies on; you write your own in Comparable, Comparator and sorting. And List is an interface too: ArrayList is one class that implements it, as the Collections Framework shows.

A first taste of interface versus abstract class#

You now know two tools that both make a class provide certain methods: the abstract class from the previous lesson and the interface from this one. They overlap, and choosing between them is a real skill. Here is the start of the comparison, enough to feel the difference.

Abstract class
Interface
Can hold fields with per-object data.
Holds no per-object data, only constants.
Can give subclasses finished methods and a constructor.
Mostly promises; default methods are the exception, and there are no constructors.
A class extends only one.
A class implements many.
Says “is a kind of”.
Says “is able to”.
Where this is going
The rows do not all point the same way, which is why the choice is interesting. When do you reach for one over the other? Interface vs abstract class answers that in full. For now, hold a rough rule: an abstract class is for a family that shares real machinery, and an interface is for a capability shared across unrelated classes.

Try it

Answer each one in your head or on paper first, then open the answer.

1
In one sentence, what is an interface, and how is the question it answers different from the question inheritance answers?
2
A class is declared class Circle implements Drawable, where Drawable has one method, void draw();, but the author forgot to write draw() in Circle. When does this fail, at compile time or at run time, and why?
3
Given Drawable d = new Square();, where both Circle and Square implement Drawable, what does d.draw() print, and what decided it?
4
Why can a class implement many interfaces but extend only one parent class? Tie your answer to what each one carries.
5
A Button class is declared implements Drawable, Clickable. Which methods does the compiler force it to provide, and what must their visibility be?

Practice

Work through these on your own. Each one builds on this page.

1
Open the Drawable[] loop in the playground. Add a third class, Triangle, that implements Drawable and prints Drawing a triangle. Put a new Triangle() in the array and run it. Confirm the loop draws the triangle without any change to the loop itself.
2
Design an interface Resizable with one method, void resize(int percent);. Make a class Photo that implements both Drawable and Resizable, print something sensible from each method, then call both methods on a Photo object.
3
Give Drawable a default method drawTwice() that calls draw() two times. Call it on a circle and a square without adding anything to either class. Then make Square override drawTwice() to print something different, and explain in a sentence why the circle still uses the default.
4
Put int MAX_SHAPES = 100; in an interface called Canvas, and print it from main as Canvas.MAX_SHAPES. Then add Canvas.MAX_SHAPES = 50; and compile the program with Java on your own computer. Write down, in one sentence, why the compiler refuses that line.

Further reading#

Short guides on this topic

Quick answers to what people search for about it, with code to run.

Spotted a mistake, or a part that did not make sense? Report it by email