What are functional interfaces and how do they relate to lambda expressions? 

A functional interface is an interface that contains exactly one abstract method. These are intended to represent a single functionality (i.e., a function) and are used as the target types for lambda expressions and method references.

@FunctionalInterface

public interface MyFunction {

    int apply(int x, int y);

}

Lambda expressions in Java are used to implement the abstract method of a functional interface in a concise way. 

MyFunction add = (a, b) -> a + b;

System.out.println(add.apply(5, 3));  // Output: 8

SOLID Principles

🧱 S – Single Responsibility Principle (SRP)

Definition: A class should have only one reason to change — it should do one thing only.

❌ Violation: 

class Invoice {

    void calculateTotal() { /* logic */ }

    void printInvoice() { /* printing logic */ }

    void saveToDatabase() { /* persistence logic */ }

}

✅ Fix:

Split responsibilities into different classes:

class InvoiceCalculator { void calculateTotal(Invoice invoice) { /* ... */ } }

class InvoicePrinter { void print(Invoice invoice) { /* ... */ } }

class InvoiceRepository { void save(Invoice invoice) { /* ... */ } }

🧱 O – Open/Closed Principle (OCP)

Definition: Software entities should be open for extension but closed for modification.

❌ Violation: 

class DiscountCalculator {

    double getDiscount(String type) {

        if (type.equals("SILVER")) return 0.1;

        else if (type.equals("GOLD")) return 0.2;

        return 0.0;

    }

}

✅ Fix (use polymorphism): 

interface DiscountPolicy {

    double getDiscount();

}


class SilverDiscount implements DiscountPolicy {

    public double getDiscount() { return 0.1; }

}


class GoldDiscount implements DiscountPolicy {

    public double getDiscount() { return 0.2; }

}

🧱 L – Liskov Substitution Principle (LSP)

Definition: Subtypes should be substitutable for their base types without breaking the application.

❌ Violation: 

class Bird { void fly() {} }

class Ostrich extends Bird { void fly() { throw new UnsupportedOperationException(); } }

✅ Fix:

Use more accurate abstractions:

interface Bird {}

interface FlyingBird extends Bird { void fly(); }


class Sparrow implements FlyingBird { public void fly() { /* ... */ } }

class Ostrich implements Bird { /* no fly method */ }

🧱 I – Interface Segregation Principle (ISP)

Definition: Clients should not be forced to depend on methods they do not use.

❌ Violation: 

interface Worker {

    void work();

    void eat();

}


class Robot implements Worker {

    public void work() { /* ok */ }

    public void eat() { /* irrelevant */ }

}

✅ Fix:

Split interfaces:

interface Workable { void work(); }

interface Eatable { void eat(); }


class Human implements Workable, Eatable { /* ... */ }

class Robot implements Workable { /* ... */ }

🧱 D – Dependency Inversion Principle (DIP)

Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions.

❌ Violation: 

class MySQLDatabase {

    void connect() { /* ... */ }

}


class OrderService {

    private MySQLDatabase db = new MySQLDatabase();

}

✅ Fix: 

interface Database {

    void connect();

}


class MySQLDatabase implements Database {

    public void connect() { /* ... */ }

}


class OrderService {

    private Database db;


    public OrderService(Database db) {

        this.db = db;

    }

}