Interfaces and Functional Interfaces in Java

Master interfaces, functional interfaces, private, static, and default interface methods, and interface evolution for the OCP 21 exam.

Table of Contents

1. Interfaces Basics

An interface defines a contract that implementing classes must follow. It specifies what methods a class must implement without providing the implementation.

1.1 Interface Declaration

Example:
// Basic interface interface Drawable {
    void draw();
    // Abstract method (implicitly public abstract) } // Interface with multiple methods interface Shape {
    double area();
    double perimeter();
    void draw();
} // Interface with constants (implicitly public static final) interface Constants {
int MAX_SIZE = 100;
String DEFAULT_NAME ="Unknown";
}

1.2 Interface Features

  • All methods are implicitly public abstract
  • All fields are implicitly public static final
  • Cannot be instantiated
  • Can extend multiple interfaces
  • Classes can implement multiple interfaces

2. Implementing Interfaces

Classes implement interfaces using the implements keyword.

2.1 Single Interface Implementation

Example:
interface Drawable {
    void draw();
}
class Circle implements Drawable {
    @Override public void draw() {
        System.out.println("Drawing circle");
    }
} Drawable drawable = new Circle();
drawable.draw();

2.2 Multiple Interface Implementation

Example:
interface Drawable {
    void draw();
}
interface Movable {
    void move();
}
class Shape implements Drawable, Movable {
    @Override public void draw() {
        System.out.println("Drawing");
    }
@Override public void move() {
    System.out.println("Moving");
}
}

3. Default Methods

Default methods (Java 8+) provide implementation in interfaces. They allow interface evolution without breaking existing implementations.

3.1 Default Method Syntax

Example:
interface Drawable {
    void draw();
    // Abstract method // Default method with implementation default void printInfo() {
        System.out.println("This is a drawable object");
    }
default void resize(int factor) {
    System.out.println("Resizing by factor:" + factor);
}
} class Circle implements Drawable {
@Override public void draw() {
    System.out.println("Drawing circle");
} // Can override default method @Override public void printInfo() {
System.out.println("This is a circle");
}
} Circle circle = new Circle();
circle.draw();
//"Drawing circle" circle.printInfo();
//"This is a circle" (overridden) circle.resize(2);
//"Resizing by factor: 2" (uses default)

3.2 Multiple Inheritance with Default Methods

Important: If a class implements multiple interfaces with the same default method signature, it must override the method to resolve the conflict.
Example:
interface A {
    default void method() {
        System.out.println("A");
    }
} interface B {
default void method() {
    System.out.println("B");
}
} // Must override to resolve conflict class C implements A, B {
@Override public void method() {
    A.super.method();
    // Call A's default method B.super.method();

        // Call B's default method System.out.println("C");
}
}

4. Static Methods

Static methods in interfaces (Java 8+) provide utility methods that belong to the interface.

Example:
interface MathUtils {
    static int add(int a, int b) {
        return a + b;
    }
static double calculateArea(double radius) {
    return Math.PI * radius * radius;
}
} // Called via interface name int result = MathUtils.add(5, 3);
double area = MathUtils.calculateArea(5.0);
// Cannot be called via implementing class instance class Calculator implements MathUtils {
}
Calculator calc = new Calculator();
// calc.add(5, 3);
// Compilation error - static methods belong to
interface

5. Private Methods

Private methods in interfaces (Java 9+) allow code reuse within default and static methods.

Example:
interface Processor {
    default void process(String data) {
        validate(data);
        transform(data);
        save(data);
    } // Private instance method (used by default methods) private void validate(String data) {
    if (data == null || data.isEmpty()) {
        throw new IllegalArgumentException("Invalid data");
    }
} // Private static method (used by static methods) private static void transform(String data) {
// Transformation logic }
static void processStatic(String data) {
    transform(data);
    // Can call private static method }
}

6. Functional Interfaces

A functional interface has exactly one abstract method. It can be implemented using lambda expressions.

6.1 @FunctionalInterface Annotation

Example:
// Functional interface @FunctionalInterface interface Calculator {
    int calculate(int a, int b);
    // Can have default methods default void printResult(int result) {
        System.out.println("Result:" + result);
    } // Can have static methods static Calculator create() {
    return (a, b) -> a + b;
} // Cannot have multiple abstract methods // void anotherMethod();
// Would break functional interface } // Implementation with lambda Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
System.out.println(add.calculate(5, 3));
// 8 System.out.println(multiply.calculate(5, 3));
// 15

6.2 Functional Interface Rules

  • Must have exactly one abstract method
  • Can have multiple default and static methods
  • Can have methods from Object class (they don't count)
  • @FunctionalInterface annotation is optional but recommended

7. Common Functional Interfaces

Java provides several built-in functional interfaces in java.util.function package.

Interface Method Description
Function<T, R> R apply(T t) Takes one argument, returns result
Predicate<T> boolean test(T t) Takes one argument, returns boolean
Consumer<T> void accept(T t) Takes one argument, returns void
Supplier<T> T get() Takes no arguments, returns value
BiFunction<T, U, R> R apply(T t, U u) Takes two arguments, returns result
Example:
import java.util.function.*;
// Function Function<
String, Integer>
length = s -> s.length();
int len = length.apply("Hello");
// 5 // Predicate Predicate<
Integer>
isEven = n -> n % 2 == 0;
boolean result = isEven.test(4);
// true // Consumer Consumer<
String>
printer = s -> System.out.println(s);
printer.accept("Hello");
// Prints"Hello" // Supplier Supplier<
String>
generator = () ->"Hello";
String value = generator.get();
//"Hello" // BiFunction BiFunction<
Integer, Integer, Integer>
add = (a, b) -> a + b;
int sum = add.apply(5, 3);
// 8

8. Interface Evolution

Interfaces can evolve over time without breaking existing implementations using default methods.

Example:
// Original interface interface Drawable {
    void draw();
} // Later, add new method without breaking existing code interface Drawable {
void draw();
// New method with default implementation default void resize(int factor) {
    System.out.println("Default resize:" + factor);
}
} // Existing implementations continue to work class Circle implements Drawable {
@Override public void draw() {
    System.out.println("Drawing circle");
} // resize() uses default implementation } // New implementations can override class Rectangle implements Drawable {
@Override public void draw() {
    System.out.println("Drawing rectangle");
}
@Override public void resize(int factor) {
    System.out.println("Custom resize:" + factor);
}
}

9. Exam Key Points

Critical Concepts for OCP 21 Exam:

  • Interface: Defines contract, methods are public abstract by default
  • Fields: public static final by default
  • Multiple Implementation: Classes can implement multiple interfaces
  • Default Methods: Provide implementation in interfaces (Java 8+)
  • Default Method Conflict: Must override if multiple interfaces have same default method
  • Static Methods: Belong to interface, called via interface name
  • Private Methods: Code reuse within interface (Java 9+)
  • Functional Interface: Exactly one abstract method
  • @FunctionalInterface: Optional annotation, enforces single abstract method
  • Lambda Expressions: Can implement functional interfaces
  • Function: Takes input, returns output
  • Predicate: Takes input, returns boolean
  • Consumer: Takes input, returns void
  • Supplier: Takes no input, returns value
  • Interface Evolution: Default methods allow adding methods without breaking code
  • super.method(): Call parent interface's default method
  • Interface.super.method(): Call specific interface's default method
  • Cannot Instantiate: Interfaces cannot be instantiated directly

Post a Comment

0 Comments