← Back to Java series
🧱
OOP
OOP · Prerequisite: previous lecture

10. Interfaces

An **interface** declares behavior to be implemented. A class implements one or more interfaces with `implements`. Since JDK 8 interfaces can carry `default` and `static` methods too — the underpinning of the Stream and functional APIs.

JavaOOPinterfacedefault method
Duration
~1.5-2 hours
Level
📊 Intermediate
Prerequisite
🎯 Previous lecture or equivalent knowledge
OUTCOME
An **interface** declares behavior to be implemented. A class implements one or more interfaces with `implements`. Since JDK 8 interfaces can carry `default` and `static` methods too — the underpinning of the Stream and functional APIs.

What you'll learn

  • 1Declare an interface and implement it with `implements`
  • 2Implement multiple interfaces in one class
  • 3Use `default` methods to provide a default implementation
  • 4Understand a functional interface (single abstract method)

Overview

An **interface** declares behavior to be implemented. A class implements one or more interfaces with `implements`. Since JDK 8 interfaces can carry `default` and `static` methods too — the underpinning of the Stream and functional APIs.

Core Concepts

1) Declaring an interface

java
interface Drawable {
    void draw();           // implicitly public abstract
}

2) `implements`

java
class Circle implements Drawable {
    @Override
    public void draw() { System.out.println("◯"); }
}

3) Multiple interfaces

java
class Sword implements Drawable, Comparable<Sword> { ... }

A class can implement many interfaces, but extend only one parent class.

4) `default` and `static` (JDK 8+)

java
interface Greeter {
    String name();

    default String greet() {           // implementation
        return "Hello, " + name() + "!";
    }

    static Greeter of(String n) {       // interface-level static
        return () -> n;
    }
}

5) Functional interface

An interface with **exactly one abstract method** is called a functional interface. Lambdas can be assigned to it. The `@FunctionalInterface` annotation is optional but documents intent.

java
@FunctionalInterface
interface Op { int apply(int x); }

Op square = x -> x * x;
System.out.println(square.apply(5));   // 25

Examples

Example 1 — `DrawableDemo.java`: basic interface

java
public class DrawableDemo {
    interface Drawable { void draw(); }
    static class Circle implements Drawable {
        @Override public void draw() { System.out.println("◯"); }
    }
    static class Square implements Drawable {
        @Override public void draw() { System.out.println("□"); }
    }

    public static void main(String[] args) {
        Drawable[] shapes = { new Circle(), new Square() };
        for (Drawable d : shapes) d.draw();
    }
}

**Output**

text
◯
□

**Note:** the contract lives in `Drawable`, while each class chooses its own implementation.

Example 2 — `MultipleImpl.java`: multiple interfaces

java
public class MultipleImpl {
    interface Run { void run(); }
    interface Swim { void swim(); }

    static class Duck implements Run, Swim {
        @Override public void run() { System.out.println("waddle"); }
        @Override public void swim() { System.out.println("paddle"); }
    }

    public static void main(String[] args) {
        Duck d = new Duck();
        d.run();
        d.swim();
    }
}

**Output**

text
waddle
paddle

Example 3 — `DefaultMethod.java`: `default` and `static`

java
public class DefaultMethod {
    interface Greeter {
        String name();

        default String greet() { return "Hello, " + name() + "!"; }

        static Greeter of(String n) { return () -> n; }
    }

    public static void main(String[] args) {
        Greeter g = Greeter.of("World");
        System.out.println(g.greet());
    }
}

**Output**

text
Hello, World!

**Note:** `default` lets you evolve interfaces without breaking existing implementations.

Example 4 — `Functional.java`: functional interface + lambda

java
public class Functional {
    @FunctionalInterface
    interface Op { int apply(int x); }

    public static void main(String[] args) {
        Op square = x -> x * x;
        Op inc = x -> x + 1;
        System.out.println(square.apply(5));
        System.out.println(inc.apply(5));
    }
}

**Output**

text
25
6

**Note:** a lambda is shorthand for implementing a functional interface.

Common Mistakes

  1. Forgetting `public` on the implementation (interface members are `public` by default)
  2. Trying to put state (fields) in an interface — only constants (`public static final`) are allowed
  3. Diamond problem with conflicting `default` methods: the implementor must override and pick
  4. Marking a class `@FunctionalInterface` when it has more than one abstract method (compile error)
  5. Confusing abstract class vs interface — interface = pure contract, abstract class = contract + partial implementation

Summary

  • Interface = behavior contract
  • A class extends one parent but can implement many interfaces
  • `default` and `static` make interfaces practical to evolve
  • Functional interfaces + lambdas (lecture 18) are how modern Java composes behavior

Practice

# Practice - 10. Interfaces

## Exercise 1 — `Sortable` interface

  • File: `Homework01.java`
  • Key concepts: interface, override

Requirements

  • Interface `Sortable` with `int order();`.
  • Class `Task(String name, int order) implements Sortable`.
  • In main create three tasks, sort by `order()` with `Arrays.sort(tasks, Comparator.comparingInt(Sortable::order))`, print in order.

Expected output

text
1: bake
2: cool
3: eat

## Exercise 2 — `Calculator` functional interface

  • File: `Homework02.java`
  • Key concepts: functional interface, lambda

Requirements

  • Functional interface `Calc { int compute(int a, int b); }`.
  • Lambdas for `add` / `sub` / `mul`.
  • Print `1 + 2 = 3`, `5 - 2 = 3`, `4 * 3 = 12`.

Expected output

text
1 + 2 = 3
5 - 2 = 3
4 * 3 = 12

## Solutions After trying it yourself, compare with [`answer/`](./answer/).

Solution code (homework/answer/)

answer/Homework01.java

java
import java.util.Arrays;
import java.util.Comparator;

/** Sortable interface. */
public class Homework01 {
    interface Sortable { int order(); }
    record Task(String name, int order) implements Sortable {}

    public static void main(String[] args) {
        Task[] tasks = { new Task("cool", 2), new Task("eat", 3), new Task("bake", 1) };
        Arrays.sort(tasks, Comparator.comparingInt(Sortable::order));
        for (Task t : tasks) System.out.println(t.order() + ": " + t.name());
    }
}

answer/Homework02.java

java
/** Calculator functional interface. */
public class Homework02 {
    @FunctionalInterface
    interface Calc { int compute(int a, int b); }

    public static void main(String[] args) {
        Calc add = (a, b) -> a + b;
        Calc sub = (a, b) -> a - b;
        Calc mul = (a, b) -> a * b;
        System.out.println("1 + 2 = " + add.compute(1, 2));
        System.out.println("5 - 2 = " + sub.compute(5, 2));
        System.out.println("4 * 3 = " + mul.compute(4, 3));
    }
}

Try It Yourself

bash
cd 02_oop/10_interface/src
javac DefaultMethod.java
java DefaultMethod

Next Lecture

[11_Arrays](../../03_컬렉션/11_배열/) — the next chapter starts: arrays and multi-dimensional arrays, then the Collections framework.

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗