Skip to content
Interfaces
step 1/7

Reading — step 1 of 7

Learn

~2 min readInheritance and Interfaces

An interface is a contract: a set of method signatures a class promises to implement. It's how Java does polymorphism without single-class-inheritance limitations. Oracle's tutorial puts this at the heart of OOP design.

Defining an interface

public interface Comparable<T> {
    int compareTo(T other);
}

public interface Drawable {
    void draw();
    void resize(int width, int height);
}

No bodies (in basic interfaces) — just method signatures. Implementing classes must provide concrete implementations.

Implementing an interface

public class Square implements Drawable {
    private int side;
    
    public Square(int side) { this.side = side; }
    
    @Override
    public void draw() {
        System.out.println("square of side " + side);
    }
    
    @Override
    public void resize(int w, int h) {
        this.side = Math.min(w, h);
    }
}

A class must provide ALL the methods declared in the interfaces it implements. The compiler verifies this.

Multiple interfaces — Java's escape from single inheritance

public class Button implements Drawable, Clickable, Focusable {
    @Override public void draw() { ... }
    @Override public void onClick() { ... }
    @Override public void onFocus() { ... }
}

A class can implement many interfaces. This is how Java does "is multiple things" without multiple inheritance complications.

Default methods (Java 8+)

Interfaces can provide a default implementation:

public interface Greetable {
    String getName();
    
    default String greet() {
        return "Hello, " + getName() + "!";
    }
}

Implementors get greet() for free. They can override it if needed. Default methods made it possible to add new methods to existing interfaces (like Iterable.forEach) without breaking everyone.

Static and constant members

public interface MathOps {
    double PI = 3.14159;       // implicitly public static final
    
    static double square(double x) {
        return x * x;
    }
}

Fields in interfaces are implicitly public static final constants. Static methods are utility helpers tied to the interface.

Functional interfaces

An interface with exactly ONE abstract method is a functional interface. You can use a lambda to implement it:

public interface Callback {
    void run(String message);
}

Callback cb = msg -> System.out.println("got: " + msg);
cb.run("hello");      // "got: hello"

java.util.function.* is full of functional interfaces: Function<T, R>, Predicate<T>, Consumer<T>, Supplier<T>. The whole Streams API runs on them.

Interface vs abstract class

  • Interface — contract. Can't have state (only constants). Use when many unrelated types share behavior.
  • Abstract class — partial implementation + state. Single inheritance. Use when there's a natural is-a hierarchy with shared concrete behavior.

Since Java 8 added default methods, the line blurred — but interfaces still can't hold mutable state.

Common mistakes

  • Forgetting @Override on interface methods — typos silently DON'T implement the interface, fooling the compiler if there's a default.
  • Storing state in an interface — fields are implicitly public static final. Real state belongs in classes.
  • Skipping interfaces in design — most well-designed Java code declares dependencies via interfaces, not concrete classes. Easier to test and substitute.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…