Interfaces

An interface is a pure contract: it defines what a class must be able to do, without saying how. Every method in an interface is implicitly public abstract unless it's marked default or static, and an interface can't hold instance fields — only constants.

Declaring and Implementing an Interface

You declare an interface with the interface keyword, and a class agrees to the contract using implements. Unlike class inheritance, where a class can only extends one superclass, a class can implements multiple interfaces at once — this is Java's workaround for not supporting multiple inheritance of classes.

Example: A Playable Contract

interface Playable {
  void play();
}

class MusicTrack implements Playable {
  private String title;

  MusicTrack(String title) {
    this.title = title;
  }

  @Override
  public void play() {
    System.out.println("Playing track: " + title);
  }
}

class VideoClip implements Playable {
  private String fileName;

  VideoClip(String fileName) {
    this.fileName = fileName;
  }

  @Override
  public void play() {
    System.out.println("Playing video: " + fileName);
  }
}

What's happening:

  • MusicTrack and VideoClip have nothing to do with each other — they don't share a superclass — but both can be treated as Playable.
  • Each class provides its own version of play(), fulfilling the interface's contract.
  • Code that only needs to "play something" can accept a Playable reference and work with either class: Playable p = new MusicTrack("Song"); p.play();

Multiple Interfaces

Because interfaces don't carry implementation state, Java allows a class to implement several of them at once — something that isn't allowed with class inheritance (a class can only extends one class).

interface Playable { void play(); }
interface Downloadable { void download(); }

class MusicTrack implements Playable, Downloadable {
  public void play() { /* ... */ }
  public void download() { /* ... */ }
}
          

default Methods

Since Java 8, interfaces can include default methods — methods with an actual body. This lets you add new behavior to an interface without breaking every class that already implements it, since existing implementers automatically inherit the default behavior unless they choose to override it.

interface Playable {
  void play();

  default void stop() {
    System.out.println("Stopped.");
  }
}
          
Note: MusicTrack and VideoClip both get a working stop() for free — they only need to implement play() unless they want custom stop behavior.
Next up: learn how to organize classes into namespaces with Packages.