SyntaxStudy
Sign Up
Java Multiple Interface Implementation and Functional Interfaces
Java Beginner 1 min read

Multiple Interface Implementation and Functional Interfaces

One of the key advantages of interfaces over abstract classes is that a class can implement any number of interfaces. This enables a class to play multiple roles simultaneously. For example, a class might implement Comparable (for natural ordering), Cloneable (to support cloning), and a custom Serializable interface. Each interface adds a set of behaviours to the class without the constraints of single inheritance. A functional interface is an interface with exactly one abstract method. Functional interfaces are the backbone of Java lambdas and method references. The @FunctionalInterface annotation asks the compiler to verify that the interface qualifies. Java provides many built-in functional interfaces in java.util.function: Function, Predicate, Consumer, Supplier, BiFunction, and more. Lambdas are anonymous implementations of functional interfaces written with arrow syntax. They make code more concise and expressive, especially when passing behaviour as a parameter (strategy pattern). Method references (ClassName::methodName) are an even shorter form of lambda when the body consists of a single method call. Together, lambdas and functional interfaces bring functional programming idioms to Java.
Example
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

// Custom functional interface
@FunctionalInterface
interface Transformer<T, R> {
    R transform(T input);
}

// Class implementing multiple interfaces
class Product implements Comparable<Product>, Cloneable {
    private final String name;
    private final double price;
    private final int    stock;

    Product(String name, double price, int stock) {
        this.name = name; this.price = price; this.stock = stock;
    }

    public String getName()  { return name; }
    public double getPrice() { return price; }
    public int    getStock() { return stock; }

    @Override
    public int compareTo(Product other) {
        return Double.compare(this.price, other.price); // natural order: by price
    }

    @Override public String toString() {
        return String.format("%-12s $%.2f (stock: %d)", name, price, stock);
    }
}

public class MultipleInterfacesDemo {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
            new Product("Laptop",   999.99, 10),
            new Product("Mouse",     29.99, 50),
            new Product("Monitor",  349.99,  8),
            new Product("Keyboard",  79.99, 30)
        );

        // Comparable — natural sort by price
        List<Product> byPrice = products.stream()
            .sorted()
            .collect(Collectors.toList());
        System.out.println("By price (natural order):");
        byPrice.forEach(System.out::println);  // method reference

        // Comparator lambda — sort by name
        System.out.println("\nBy name:");
        products.stream()
            .sorted(Comparator.comparing(Product::getName))
            .forEach(p -> System.out.println("  " + p));

        // Predicate — filter in stock
        Predicate<Product> inStock = p -> p.getStock() > 0;
        Predicate<Product> affordable = p -> p.getPrice() < 100;

        System.out.println("\nAffordable items in stock:");
        products.stream()
            .filter(inStock.and(affordable))
            .forEach(p -> System.out.println("  " + p));

        // Custom functional interface used with lambda
        Transformer<String, Integer> wordCount = s -> s.trim().split("\\s+").length;
        System.out.println("\nWord count: " + wordCount.transform("Hello Java World")); // 3

        // Built-in Function
        Function<Product, String> summary = p ->
            p.getName() + " costs $" + p.getPrice();
        products.forEach(p -> System.out.println(summary.apply(p)));
    }
}