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;
}
}