Skip to content
intermediatePhase 11 · Java OOP

Interfaces

Define and implement interfaces, default methods, and multiple inheritance.

45m
2 problems
Topic Progress0%

Interface Basics

Interface Definition

An interface defines a contract that implementing classes must follow.

Basic Interface

public interface Drawable {
    void draw();
    int getArea();
}

// Implement interface
public class Circle implements Drawable {
    double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("Drawing circle");
    }
    
    @Override
    public int getArea() {
        return (int) (Math.PI * radius * radius);
    }
}

Interface Variables

public interface Constants {
    // All variables are implicitly public static final
    int MAX_SIZE = 100;  // public static final
    String APP_NAME = "MyApp";
    
    // int count;  // COMPILE ERROR - must initialize
}

Interface Methods

public interface Example {
    // Implicitly public abstract
    void method1();  // public abstract
    
    // All methods are public
    // Cannot have private, protected, or default methods (pre-Java 8)
}

Multiple Interface Implementation

public interface Flyable {
    void fly();
}

public interface Swimmable {
    void swim();
}

public class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("Duck flying");
    }
    
    @Override
    public void swim() {
        System.out.println("Duck swimming");
    }
}

Interface Inheritance

public interface Shape {
    double area();
}

public interface Resizable extends Shape {
    void resize(double factor);
}

// Implementing Resizable must implement both area() and resize()
public class Circle implements Resizable {
    double radius;
    
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public void resize(double factor) {
        radius *= factor;
    }
}

Default Methods

Default Methods (Java 8+)

Default methods provide implementation in interfaces.

Basic Default Method

public interface Greeting {
    void greet();
    
    // Default method - has implementation
    default void greetWithTime() {
        greet();
        System.out.println("Have a nice day!");
    }
}

public class EnglishGreeting implements Greeting {
    @Override
    public void greet() {
        System.out.println("Hello!");
    }
    // greetWithTime() inherited automatically
}

EnglishGreeting g = new EnglishGreeting();
g.greetWithTime();
// Output:
// Hello!
// Have a nice day!

Override Default Method

public interface Greeting {
    default void greet() {
        System.out.println("Default greeting");
    }
}

public class CustomGreeting implements Greeting {
    @Override
    public void greet() {
        System.out.println("Custom greeting");
    }
}

Multiple Inheritance with Defaults

public interface A {
    default void hello() {
        System.out.println("A's hello");
    }
}

public interface B {
    default void hello() {
        System.out.println("B's hello");
    }
}

// Must resolve conflict
public class C implements A, B {
    @Override
    public void hello() {
        // Must provide implementation
        A.super.hello();  // Or B.super.hello()
    }
}

Static Methods

public interface MathUtils {
    static int square(int n) {
        return n * n;
    }
    
    static int cube(int n) {
        return n * n * n;
    }
}

// Call without implementing
int result = MathUtils.square(5);  // 25

Practical Example

public interface List<E> {
    int size();
    boolean isEmpty();
    
    // Default methods
    default boolean isNotEmpty() {
        return !isEmpty();
    }
    
    default void printAll() {
        for (E item : this) {
            System.out.println(item);
        }
    }
}

Multiple Inheritance

Multiple Inheritance Through Interfaces

Java supports multiple inheritance via interfaces.

Basic Multiple Inheritance

public interface Flyable {
    void fly();
}

public interface Swimmable {
    void swim();
}

public interface Runnable {
    void run();
}

public class Duck implements Flyable, Swimmable, Runnable {
    @Override
    public void fly() { System.out.println("Flying"); }
    
    @Override
    public void swim() { System.out.println("Swimming"); }
    
    @Override
    public void run() { System.out.println("Running"); }
}

Resolving Conflicts

public interface A {
    default void hello() { System.out.println("A"); }
    default void world() { System.out.println("A world"); }
}

public interface B {
    default void hello() { System.out.println("B"); }
}

public class C implements A, B {
    @Override
    public void hello() {
        A.super.hello();  // Explicit choice
    }
    // world() inherited from A
}

Interface vs Abstract Class for Inheritance

// Abstract class: single inheritance with state
public abstract class Animal {
    protected String name;
    public abstract void makeSound();
}

// Interface: multiple inheritance, no state
public interface Pet {
    void play();
}

public interface Flyable {
    void fly();
}

// Dog gets Animal's state + Pet + Flyable capabilities
public class Dog extends Animal implements Pet, Flyable {
    public void makeSound() { }
    public void play() { }
    public void fly() { }
}

Design Pattern: Mixin

public interface Timestamped {
    default long getTimestamp() {
        return System.currentTimeMillis();
    }
}

public interface Logged {
    default void log(String message) {
        System.out.println("[LOG] " + message);
    }
}

public class Service implements Timestamped, Logged {
    // Gets both capabilities without inheritance
}

Functional Interfaces

Functional Interfaces

Interfaces with exactly one abstract method, used with lambda expressions.

Basic Functional Interface

@FunctionalInterface
public interface Calculator {
    int calculate(int a, int b);  // Only one abstract method
    
    // Can have default and static methods
    default void print() {
        System.out.println("Calculator");
    }
}

// Using lambda
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;

int sum = add.calculate(5, 3);      // 8
int product = multiply.calculate(5, 3);  // 15

Built-in Functional Interfaces

// Predicate<T> - takes T, returns boolean
Predicate<String> isEmpty = s -> s.isEmpty();

// Function<T, R> - takes T, returns R
Function<String, Integer> length = s -> s.length();

// Consumer<T> - takes T, returns void
Consumer<String> printer = s -> System.out.println(s);

// Supplier<T> - takes nothing, returns T
Supplier<String> hello = () -> "Hello";

// UnaryOperator<T> - takes T, returns T
UnaryOperator<String> upper = s -> s.toUpperCase();

// BinaryOperator<T> - takes T, T, returns T
BinaryOperator<Integer> add = (a, b) -> a + b;

Method References

// Lambda
Function<String, Integer> length = s -> s.length();

// Method reference
Function<String, Integer> length2 = String::length;

// Both do the same thing
int len = length.apply("hello");  // 5

Practical Examples

// Sort with Comparator
List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
names.sort((a, b) -> a.compareTo(b));
names.sort(String::compareTo);  // Method reference

// Filter with Predicate
List<String> filtered = names.stream()
    .filter(s -> s.length() > 3)
    .collect(Collectors.toList());

// Transform with Function
List<Integer> lengths = names.stream()
    .map(String::length)
    .collect(Collectors.toList());

@FunctionalInterface Annotation

@FunctionalInterface
public interface MyInterface {
    void doSomething();
    
    // Can have default methods
    default void helper() { }
    
    // Can have static methods
    static void utility() { }
    
    // But only ONE abstract method
    // void anotherMethod();  // COMPILE ERROR!
}

Practice Problems

0/3solved
Design LRU Cache
Interface Design

Design a Least Recently Used cache.

Example:

Input: put(1, 1), get(1)

Output: 1

LRU cache operations

Optimal Solution — O(1) time, O(n) space

Use LinkedHashMap or custom implementation.

class LRUCache {
    private int capacity;
    private Map<Integer, Node> map;
    private Node head, tail;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        map = new HashMap<>();
        head = new Node(0, 0);
        tail = new Node(0, 0);
        head.next = tail;
        tail.prev = head;
    }
}

Edge Cases:

  • Capacity 1
  • Get non-existent
  • Update existing
Design Stack with Min
Interface Design

Design a stack that supports getMin() in O(1).

Example:

Input: push(3), push(5), getMin()

Output: 3

Track minimum element

Optimal Solution — O(1) time, O(n) space

Use two stacks or track min with each element.

class MinStack {
    private Stack<Integer> stack;
    private Stack<Integer> minStack;
    
    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);
        if (minStack.isEmpty() || val <= minStack.peek())
            minStack.push(val);
    }
}

Edge Cases:

  • Pop when empty
  • All same values
  • Negative values
Design Iterator
Interface Implementation

Design an iterator for a collection.

Example:

Input: hasNext(), next()

Output: element

Standard iterator pattern

Optimal Solution — O(1) time, O(1) space

Implement Iterator interface.

class MyIterator implements Iterator<Integer> {
    private List<Integer> list;
    private int index = 0;
    
    public MyIterator(List<Integer> list) { this.list = list; }
    public boolean hasNext() { return index < list.size(); }
    public Integer next() { return list.get(index++); }
}

Edge Cases:

  • Empty collection
  • Single element
  • Concurrent modification

Quiz

1. What is a functional interface?

Question 1 options

2. Can an interface have constructors?

Question 2 options

3. What is a default method?

Question 3 options

4. Can a class implement multiple interfaces?

Question 4 options

Flashcards

Question

What is the difference between abstract class and interface?

Answer

Abstract class: single inheritance, constructors, state. Interface: multiple inheritance, no constructors, limited state.

Question

What is a functional interface?

Answer

Interface with exactly one abstract method, used with lambda expressions. Annotated with @FunctionalInterface.

Question

What is a default method?

Answer

A method in an interface with a body. Java 8+ feature. Can be overridden by implementing class.

Question

Can interfaces have instance variables?

Answer

No. Interface variables are implicitly public static final (constants only).

Question

What is Interfaces?

Answer

Interfaces is a key concept in Java programming.

Revision Notes

Key Takeaways

  • 1.Interfaces define contracts
  • 2.Default methods provide implementation
  • 3.Functional interfaces enable lambdas
  • 4.Multiple interfaces enable multiple inheritance

Interview Tips

  • Know difference between interface and abstract class
  • Understand default method conflicts
  • Use functional interfaces with lambdas
  • Practice interface design patterns

Cheat Sheet

Cheat Sheet

  • interface: defines contract
  • implements: use interface
  • default method: has body (Java 8+)
  • static method: belongs to interface
  • @FunctionalInterface: one abstract method
  • Multiple interfaces: class A implements B, C