SOLID Principles in Java: A Beginner-Friendly Guide With Real Examples
Learn the five SOLID principles in Java with simple examples, practical use cases, interview questions, and easy memory tricks. Build better Java applications and prepare confidently for Java developer jobs.
If you are learning Java for your first developer job, one topic you will frequently encounter in interviews is SOLID principles. SOLID is not a Java feature or a set of keywords. It is a collection of five object-oriented design principles that help developers write code that is easier to understand, maintain, test, and extend.
For beginners, the good news is that you do not need to memorize complicated definitions. Once you understand the problem each principle tries to solve, SOLID becomes much easier.
What Does SOLID Stand For?
Single Responsibility Principle
A class should have one main responsibility or one reason to change.
Open/Closed Principle
Software should be open for extension but closed for unnecessary modification.
Liskov Substitution Principle
A child class should be usable wherever its parent class is expected.
Interface Segregation Principle
Classes should not be forced to depend on methods they do not need.
Dependency Inversion Principle
High-level code should depend on abstractions rather than concrete implementations.
1. Single Responsibility Principle — SRP
The Single Responsibility Principle says that a class should have one responsibility or one reason to change.
Imagine an Employee class that calculates salary, saves employee data,
sends emails, generates PDF reports, and writes audit logs. The class has too many
responsibilities.
Example of a problematic design
class EmployeeService {
void calculateSalary() {
// salary calculation
}
void saveEmployee() {
// database operation
}
void sendEmail() {
// email operation
}
void generateReport() {
// report generation
}
}
If the email system changes, this class changes. If the database changes, it changes again. If reporting requirements change, it changes again.
A cleaner design
class SalaryCalculator {
void calculateSalary() {
// salary calculation
}
}
class EmployeeRepository {
void saveEmployee() {
// database operation
}
}
class EmailService {
void sendEmail() {
// email operation
}
}
class ReportGenerator {
void generateReport() {
// report generation
}
}
2. Open/Closed Principle — OCP
The Open/Closed Principle means that software should be open for extension but closed for modification.
Consider a payment application. A beginner might create one large class containing
many if-else conditions for every payment type.
class PaymentService {
void pay(String type) {
if (type.equals("CARD")) {
// Card payment
}
else if (type.equals("UPI")) {
// UPI payment
}
}
}
When PayPal or another payment method is added, the existing class must be modified. As the number of payment methods grows, the class becomes harder to maintain.
A better approach
interface Payment {
void pay();
}
class CardPayment implements Payment {
public void pay() {
System.out.println("Card payment");
}
}
class UpiPayment implements Payment {
public void pay() {
System.out.println("UPI payment");
}
}
class PaypalPayment implements Payment {
public void pay() {
System.out.println("PayPal payment");
}
}
Now a new payment type can be added as another implementation instead of repeatedly changing existing payment logic.
3. Liskov Substitution Principle — LSP
The Liskov Substitution Principle is mainly about inheritance and correct behavior. A subclass should be usable wherever its parent class is expected without breaking the application.
A common example
class Bird {
void fly() {
System.out.println("Flying");
}
}
class Sparrow extends Bird {
// Sparrow can fly
}
class Penguin extends Bird {
void fly() {
throw new UnsupportedOperationException();
}
}
The problem is that the parent class promises a flying behavior, but a penguin cannot actually provide that behavior. This suggests that the inheritance design is incorrect.
A better design can separate flying behavior into a dedicated abstraction so that only birds capable of flying implement it.
interface Flyable {
void fly();
}
class Sparrow implements Flyable {
public void fly() {
System.out.println("Sparrow is flying");
}
}
class Penguin {
// Penguin does not implement Flyable
}
4. Interface Segregation Principle — ISP
The Interface Segregation Principle says that a class should not be forced to implement methods it does not need.
Suppose we create one large interface for machines:
interface Machine {
void print();
void scan();
void fax();
}
A simple printer may only print. Forcing it to implement scanning and faxing creates unnecessary methods.
Better design
interface Printable {
void print();
}
interface Scannable {
void scan();
}
interface Faxable {
void fax();
}
class SimplePrinter implements Printable {
public void print() {
System.out.println("Printing...");
}
}
5. Dependency Inversion Principle — DIP
The Dependency Inversion Principle says that high-level modules should depend on abstractions rather than concrete implementations.
Consider an order service that directly creates a MySQL database object:
class OrderService {
private MySQLDatabase database = new MySQLDatabase();
}
This creates tight coupling. If the application later needs PostgreSQL, the
OrderService has to change.
Better design using an abstraction
interface Database {
void save();
}
class MySQLDatabase implements Database {
public void save() {
System.out.println("Saving to MySQL");
}
}
class PostgreSQLDatabase implements Database {
public void save() {
System.out.println("Saving to PostgreSQL");
}
}
class OrderService {
private Database database;
OrderService(Database database) {
this.database = database;
}
}
Now OrderService depends on the Database interface instead
of directly depending on MySQL.
SOLID Principles at a Glance
| Principle | Full Form | Beginner Meaning | Interview Keyword |
|---|---|---|---|
| S | Single Responsibility | One class should have one main responsibility. | One reason to change |
| O | Open/Closed | Extend behavior without unnecessary modification. | Extension |
| L | Liskov Substitution | Child should work correctly as the parent. | Inheritance |
| I | Interface Segregation | Don't force classes to implement unnecessary methods. | Small interfaces |
| D | Dependency Inversion | Depend on abstractions rather than concrete implementations. | Loose coupling |
SOLID Example From a Real Java Application
Imagine you are developing an e-commerce application.
SRP
Keep order calculation, payment processing, email notifications and persistence in separate responsibilities.
OCP
Add new payment methods through new implementations rather than modifying a large existing payment class.
LSP
Ensure subclasses provide behavior consistent with the contract of their parent.
ISP
Create focused interfaces instead of forcing every implementation to support unrelated operations.
DIP
Make services depend on interfaces such as Payment or
Repository, rather than concrete classes.
Why Are SOLID Principles Important for Java Developers?
SOLID principles become especially useful as applications grow. A small Java project may work even with tightly coupled classes, but a large production application can become difficult to change when responsibilities and dependencies are mixed together.
- Improves code maintainability
- Makes applications easier to test
- Reduces unnecessary coupling
- Makes new features easier to introduce
- Improves readability and code organization
- Supports cleaner object-oriented design
- Helps developers reason about production issues more effectively
SOLID and Dependency Injection: Are They the Same?
No. This is a common beginner interview question.
Dependency Inversion Principle (DIP) is a design principle. Dependency Injection (DI) is a technique used to provide dependencies to an object instead of making the object create those dependencies itself.
Common Java Interview Questions on SOLID
Question 1: What is SOLID?
SOLID is a collection of five object-oriented design principles that help developers create software that is maintainable, extensible, testable and loosely coupled.
Question 2: What is SRP?
SRP means a class should have one responsibility or one reason to change.
Question 3: What is OCP?
OCP means software should be open for extension but closed for unnecessary modification.
Question 4: What is LSP?
LSP means a subclass should be usable wherever its parent class is expected without breaking the expected behavior.
Question 5: What is ISP?
ISP means clients should not be forced to depend on methods they do not need.
Question 6: What is DIP?
DIP means high-level modules should depend on abstractions rather than concrete implementations.
How to Explain SOLID in a Java Interview
A simple interview-ready answer is:
“SOLID represents five object-oriented design principles. SRP says a class should have one responsibility. OCP says code should be open for extension but closed for unnecessary modification. LSP says subclasses should be substitutable for their parent classes. ISP recommends small and focused interfaces. DIP says high-level modules should depend on abstractions rather than concrete implementations.”
For a fresher interview, don't stop at the definition. Give a small Java example and explain the problem that the principle solves.
Easy Way to Remember SOLID
- S — Single Job: One class should have one main responsibility.
- O — Open for Extension: Add new behavior without unnecessarily changing existing code.
- L — Substitute: Child classes should correctly work wherever the parent is expected.
- I — Small Interfaces: Don't force classes to implement methods they don't need.
- D — Depend on Abstractions: Prefer interfaces/abstractions over concrete implementations.
Final Takeaway
SOLID is not about writing more classes just for the sake of following a rule. The goal is to make software easier to understand, test, maintain and extend. As a Java developer, learn to recognize the design problem first and then decide whether a SOLID principle provides a useful solution.
If you are preparing for a Java developer interview, start with the basics of OOP, then learn SOLID, exception handling, collections, Java 8+ features, multithreading, Spring/Spring Boot, SQL and REST APIs. Most importantly, practice explaining each concept with a small real-world example.
Learn Today. Lead Tomorrow.
Build your Java, programming and career skills step by step with practical, beginner-friendly learning resources.
Keep learning. Keep building. Keep growing.
Explore Eduanr.com
Learn SOLID principles in Java with simple real-world examples. Understand SRP, OCP, LSP, ISP, and DIP, improve your Java OOP skills, and prepare for developer interviews and jobs with practical explanations and examples.
ReplyDelete