Phase 2 · Object-Oriented JavaModule 10~44 min read

Interfaces, Enums, Records & Nested Types

Contracts with interfaces, type-safe constants with enums, concise data carriers with records, and nested types.

What you'll learn

Beyond plain classes, Java offers specialised type-building tools: interfaces for contracts, enums for fixed sets of constants, records for concise data carriers, and several kinds of nested class. Each removes boilerplate and makes your intent crystal clear.

By the end you'll be able to:

  • Define contracts with interfaces and implement several at once
  • Add shared behaviour with default and static interface methods
  • Recognise a functional interface and back it with a lambda
  • Model fixed choices with enums (including fields and methods)
  • Create immutable data types in one line with records
  • Restrict a hierarchy with sealed types and use nested classes

Interfaces

An interface is a pure contract: a list of methods a class promises to provide, with no implementation of its own. A class implements an interface and supplies the bodies. Crucially, a class can implement many interfaces (unlike extends, which allows only one parent) — that's Java's answer to multiple inheritance:

Interfaces.java
interface Drawable { void draw(); }
interface Clickable { void onClick(); }

class Button implements Drawable, Clickable {   // implement MANY
    public void draw()    { System.out.println("Drawing a button"); }
    public void onClick() { System.out.println("Button clicked"); }
}

public class Main {
    public static void main(String[] args) {
        Button b = new Button();
        b.draw();
        b.onClick();
    }
}
Interface vs abstract class

Interface

  • • A pure contract of what to do
  • • A class can implement many
  • • No constructors, no instance state
  • • Answers "can-do" (Comparable, Runnable)

Abstract class

  • • A partial base with shared code
  • • A class can extend only one
  • • Can have constructors & fields
  • • Answers "is-a" (Shape, Animal)
Reach for an interface for capabilities; an abstract class for a shared base.

Default, static & private methods

Since Java 8, interfaces can carry default methods — real implementations that every implementer inherits automatically, so you can add behaviour to an interface without breaking existing classes. Interfaces can also have static helper methods and private methods (to share code between defaults). Any variable declared in an interface is implicitly a public static final constant.

Default.java
interface Greeter {
    String name();                 // abstract: implementer provides it

    default void greet() {         // default: has a body, inherited free
        System.out.println("Hello, " + name());
    }
}

class Person implements Greeter {
    public String name() { return "Sara"; }
}

public class Main {
    public static void main(String[] args) {
        new Person().greet();
    }
}

Functional interfaces

An interface with exactly one abstract method is a functional interface. These are special because a lambda expression can stand in for one — a compact way to pass behaviour around. The @FunctionalInterface annotation makes the compiler enforce the "one method" rule:

Functional.java
@FunctionalInterface
interface Operation {
    int apply(int a, int b);       // exactly ONE abstract method
}

public class Main {
    public static void main(String[] args) {
        Operation add = (a, b) -> a + b;   // a lambda!
        Operation mul = (a, b) -> a * b;

        System.out.println(add.apply(3, 4));   // 7
        System.out.println(mul.apply(3, 4));   // 12
    }
}

Note

This is a first taste of functional programming — the foundation of lambdas and streams, which get full modules of their own (17 & 18). Interfaces like Runnable, Comparator, and Predicate are all functional interfaces.

Enums

When a value can only be one of a fixed set — days of the week, card suits, order states — use an enum. It gives you type safety (the compiler rejects invalid values) and readable code. Enums can also have fields, constructors, and methods, making them far more powerful than plain constants:

Enum.java
enum Day {
    MON, TUE, WED, THU, FRI, SAT, SUN;

    boolean isWeekend() {
        return this == SAT || this == SUN;
    }
}

public class Main {
    public static void main(String[] args) {
        Day today = Day.SAT;
        System.out.println(today);             // SAT
        System.out.println(today.isWeekend()); // true
    }
}
EnumFields.java
enum Planet {
    EARTH(9.81), MARS(3.71), MOON(1.62);   // each constant calls the constructor

    final double gravity;
    Planet(double g) { this.gravity = g; }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Planet.MARS.gravity);
    }
}

Records

So often you just need a small, immutable bundle of data — a point, a coordinate, a response object. Traditionally that meant writing dozens of lines of fields, getters, equals, hashCode, and toString. A record (Java 16+) generates all of that from a single line:

Records eliminate boilerplate

A traditional data class

Fields + constructor + getters + equals() + hashCode() + toString() — easily 40+ lines of boilerplate.

The same thing as a record

record Point(int x, int y) {}

One line. Java generates the rest for you.

Record.java
record Point(int x, int y) { }   // that's the whole class!

public class Main {
    public static void main(String[] args) {
        Point p = new Point(3, 4);
        System.out.println(p.x());                    // auto getter
        System.out.println(p);                        // auto toString
        System.out.println(p.equals(new Point(3, 4))); // auto equals
    }
}

Tip

Records are immutable — their fields are final. They're perfect for data transfer objects and values you want to compare by content. You can still add methods and validation in a compact constructor when needed.

Sealed classes & interfaces

A sealed type restricts which classes may extend or implement it, using a permits clause. This gives you a closed, known set of subtypes — which pairs beautifully with pattern-matching switch (the compiler knows every case):

Shape.java
sealed interface Shape permits Circle, Square { }

record Circle(double r) implements Shape { }
record Square(double side) implements Shape { }

Nested classes

Java lets you declare a class inside another. There are four flavours:

  • Static nested class — a helper grouped inside its outer class, but independent of any instance
  • Inner class — non-static; tied to an instance of the outer class and can access its fields
  • Local class — declared inside a method
  • Anonymous class — a one-off class with no name, defined and instantiated at once

Anonymous classes are the most common — often used to implement an interface on the spot:

Anonymous.java
public class Main {
    public static void main(String[] args) {
        Runnable task = new Runnable() {   // anonymous class
            public void run() {
                System.out.println("Running the task!");
            }
        };
        task.run();
    }
}

Note

For functional interfaces, a lambda (Runnable task = () -> System.out.println(...)) is a cleaner replacement for an anonymous class — which is exactly where we're headed in Module 17.

Recap & quick check

Key takeaways

  • An interface is a contract; a class can implement many (multiple inheritance of type).
  • Default methods let interfaces ship real behaviour without breaking implementers.
  • A functional interface has one abstract method and can be backed by a lambda.
  • Enums model a fixed set of type-safe constants and can hold fields and methods.
  • Records generate constructor/getters/equals/hashCode/toString for immutable data in one line.

Quick check

1. How many interfaces can a single class implement?

2. What defines a functional interface?

3. What does a record automatically generate?

4. When should you use an enum?

5. A default method in an interface…

Great progress — your OOP toolkit is now rich and modern. Next up: Module 11 — Packages, Access Control & Project Organization.