Object-Oriented Programming in Java
1. Classes and Objects
Concept
A class is a blueprint; an object is an instance of that class.
Example
java
class Car {
String model;
int year;
void start() {
[Link](model + " is starting");
}
}
// Usage
Car myCar = new Car();
[Link] = "Tesla";
[Link] = 2024;
[Link]();
Principles Applied
Abstraction: Hiding complex details, showing only essentials
Encapsulation: Bundling data and methods together
2. Encapsulation
Concept
Bundling data (fields) and methods that operate on data into a single unit, restricting direct access
to some components.
Example
java
class BankAccount {
private double balance; // Private field
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public double getBalance() {
return balance;
}
// Cannot directly access: [Link]
// Must use: [Link]()
}
Principles Applied
Information Hiding: Hide internal state, expose only necessary operations
Single Responsibility: Each method has one clear purpose
DRY (Don't Repeat Yourself): Validation logic in one place
Benefits
Data integrity (validation in setters)
Flexibility to change implementation
Controlled access
3. Inheritance
Concept
A class (child/subclass) inherits properties and methods from another class (parent/superclass).
Example
java
class Vehicle {
protected String brand;
public void honk() {
[Link]("Beep!");
}
}
class Car extends Vehicle {
private int doors;
public void displayInfo() {
[Link](brand + " has " + doors + " doors");
}
}
// Usage
Car car = new Car();
[Link] = "Honda";
[Link](); // Inherited method
Principles Applied
DRY: Reuse code from parent class instead of duplicating
Code Reusability: Write once, use in multiple subclasses
IS-A Relationship: Car IS-A Vehicle
Types of Inheritance
java
// Single Inheritance
class Dog extends Animal { }
// Multilevel Inheritance
class Puppy extends Dog { }
// Hierarchical Inheritance
class Cat extends Animal { }
class Dog extends Animal { }
// Note: Java doesn't support multiple inheritance with classes
// (but does with interfaces)
LinkedIn: Japneet Sachdeva
4. Polymorphism
Concept
"Many forms" - same entity behaves differently in different scenarios.
4.1 Compile-Time Polymorphism (Method Overloading)
java
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
Principles Applied:
DRY: Same method name for similar operations
Readability: Intuitive API design
4.2 Runtime Polymorphism (Method Overriding)
java
class Animal {
void makeSound() {
[Link]("Some sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
[Link]("Bark");
}
}
class Cat extends Animal {
@Override
void makeSound() {
[Link]("Meow");
}
}
// Usage
Animal animal1 = new Dog();
Animal animal2 = new Cat();
[Link](); // Output: Bark
[Link](); // Output: Meow
Principles Applied:
Open/Closed Principle: Open for extension, closed for modification
Liskov Substitution Principle: Subclass can replace parent class
DRY: Define behavior once, customize in subclasses
5. Abstraction
Concept
Hiding implementation details, showing only functionality.
5.1 Abstract Classes
java
abstract class Shape {
abstract double calculateArea(); // No implementation
void display() { // Concrete method
[Link]("Area: " + calculateArea());
}
}
class Circle extends Shape {
double radius;
@Override
double calculateArea() {
return [Link] * radius * radius;
}
}
class Rectangle extends Shape {
double length, width;
@Override
double calculateArea() {
return length * width;
}
}
Characteristics:
Can have both abstract and concrete methods
Can have constructors
Can have instance variables
Cannot be instantiated
Use extends keyword
Principles Applied:
Abstraction: Hide complex calculations
Template Method Pattern: Define skeleton in parent
DRY: Common behavior in parent class
5.2 Interfaces
java
interface Drawable {
void draw(); // public abstract by default
}
interface Resizable {
void resize(int percentage);
}
class Square implements Drawable, Resizable {
@Override
public void draw() {
[Link]("Drawing square");
}
@Override
public void resize(int percentage) {
[Link]("Resizing by " + percentage + "%");
}
}
Characteristics (Before Java 8):
Only abstract methods
Only constants (public static final)
Cannot have constructors
Use implements keyword
Multiple inheritance allowed
Principles Applied:
Dependency Inversion: Depend on abstractions, not concrete classes
Interface Segregation: Client shouldn't depend on methods it doesn't use
Contract Definition: Guarantees specific behavior
LinkedIn: Japneet Sachdeva
6. Abstract Classes vs Interfaces
Classic Differences (Java 7 and Earlier)
Feature Abstract Class Interface
Methods Abstract + Concrete Only Abstract
Variables Any type Only constants
Constructor Yes No
Access Modifiers Any Public only
Multiple Inheritance No Yes
Use Case IS-A relationship CAN-DO relationship
Example: When to Use What
java
// Abstract Class: IS-A relationship
abstract class Employee {
protected String name;
protected double salary;
abstract double calculateBonus();
}
class Manager extends Employee {
double calculateBonus() {
return salary * 0.2;
}
}
// Interface: CAN-DO capability
interface Flyable {
void fly();
}
class Bird implements Flyable {
public void fly() {
[Link]("Flying");
}
}
7. Modern Java Changes (Java 8+)
7.1 Default Methods in Interfaces (Java 8)
java
interface Vehicle {
void start(); // Abstract
default void stop() { // Default implementation
[Link]("Vehicle stopping");
}
}
class Car implements Vehicle {
public void start() {
[Link]("Car starting");
}
// Can use default stop() or override it
}
Why This Change?
Backward compatibility
Add new methods without breaking existing implementations
Principle: Open/Closed - extend functionality without modification
7.2 Static Methods in Interfaces (Java 8)
java
interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
// Usage
int result = [Link](5, 3);
7.3 Private Methods in Interfaces (Java 9)
java
interface Logger {
default void logInfo(String message) {
log(message, "INFO");
}
default void logError(String message) {
log(message, "ERROR");
}
private void log(String message, String level) {
[Link](level + ": " + message);
}
}
Principles Applied:
DRY: Reuse common logic in private methods
Encapsulation: Hide implementation details
7.4 Functional Interfaces (Java 8)
java
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
// Lambda expression
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
[Link]([Link](5, 3)); // 8
LinkedIn: Japneet Sachdeva
8. Modern Interface vs Abstract Class Decision
After Java 8, When to Use What?
Use Interface When:
Multiple inheritance needed
Defining a contract/capability
No shared state required
Behavior can be added via default methods
Use Abstract Class When:
Code reuse with state (instance variables)
Need constructors
Need protected/private members
Strong IS-A relationship
Example: Modern Design
java
// Interface for capability
interface Searchable {
List<String> search(String keyword);
default List<String> searchIgnoreCase(String keyword) {
return search([Link]());
}
}
// Abstract class for shared state
abstract class Database {
protected String connectionString;
abstract void connect();
void disconnect() {
[Link]("Disconnecting...");
}
}
// Concrete implementation
class MySQLDatabase extends Database implements Searchable {
@Override
void connect() {
[Link]("Connecting to MySQL");
}
@Override
public List<String> search(String keyword) {
// Implementation
return new ArrayList<>();
}
}
9. SOLID Principles in OOP
9.1 Single Responsibility Principle (SRP)
A class should have only one reason to change.
java
// Bad: Multiple responsibilities
class Employee {
void calculateSalary() { }
void saveToDatabase() { }
void sendEmail() { }
}
// Good: Separate concerns
class Employee {
void calculateSalary() { }
}
class EmployeeRepository {
void saveToDatabase(Employee emp) { }
}
class EmailService {
void sendEmail(Employee emp) { }
}
9.2 Open/Closed Principle (OCP)
Open for extension, closed for modification.
java
// Using abstraction for extension
interface PaymentProcessor {
void processPayment(double amount);
}
class CreditCardProcessor implements PaymentProcessor {
public void processPayment(double amount) {
// Credit card logic
}
}
class PayPalProcessor implements PaymentProcessor {
public void processPayment(double amount) {
// PayPal logic
}
}
// Add new payment method without modifying existing code
class CryptoProcessor implements PaymentProcessor {
public void processPayment(double amount) {
// Crypto logic
}
}
9.3 Liskov Substitution Principle (LSP)
Subclasses should be substitutable for their base classes.
java
class Rectangle {
protected int width, height;
void setWidth(int width) {
[Link] = width;
}
void setHeight(int height) {
[Link] = height;
}
int getArea() {
return width * height;
}
}
// Bad: Square violates LSP
class Square extends Rectangle {
@Override
void setWidth(int width) {
[Link] = width;
[Link] = width; // Violates expectation
}
}
// Good: Use composition or separate hierarchy
9.4 Interface Segregation Principle (ISP)
Clients shouldn't depend on interfaces they don't use.
java
// Bad: Fat interface
interface Worker {
void work();
void eat();
void sleep();
}
// Good: Segregated interfaces
interface Workable {
void work();
}
interface Eatable {
void eat();
}
class Human implements Workable, Eatable {
public void work() { }
public void eat() { }
}
class Robot implements Workable {
public void work() { }
// Robot doesn't need eat()
}
9.5 Dependency Inversion Principle (DIP)
Depend on abstractions, not concretions.
java
// Bad: High-level depends on low-level
class EmailSender {
void send(String message) { }
}
class NotificationService {
private EmailSender sender = new EmailSender(); // Tight coupling
}
// Good: Both depend on abstraction
interface MessageSender {
void send(String message);
}
class EmailSender implements MessageSender {
public void send(String message) { }
}
class SMSSender implements MessageSender {
public void send(String message) { }
}
class NotificationService {
private MessageSender sender; // Depends on abstraction
NotificationService(MessageSender sender) {
[Link] = sender;
}
}
LinkedIn: Japneet Sachdeva
10. Additional OOP Principles
10.1 DRY (Don't Repeat Yourself)
java
// Bad
class UserValidator {
boolean validateEmail(String email) {
return [Link]("@") && [Link](".");
}
boolean validateContactEmail(String email) {
return [Link]("@") && [Link]("."); // Repeated
}
}
// Good
class UserValidator {
boolean validateEmail(String email) {
return [Link]("@") && [Link](".");
}
boolean validateContactEmail(String email) {
return validateEmail(email); // Reuse
}
}
10.2 KISS (Keep It Simple, Stupid)
java
// Bad: Overcomplicated
class Calculator {
int add(int a, int b) {
return [Link](a, b).reduce(0, Integer::sum);
}
}
// Good: Simple
class Calculator {
int add(int a, int b) {
return a + b;
}
}
10.3 YAGNI (You Aren't Gonna Need It)
Don't add functionality until needed.
java
// Bad: Premature optimization
class User {
String name;
String email;
String phone; // Added "just in case"
String address; // Not needed yet
String emergencyContact; // Not needed yet
}
// Good: Add only what's needed now
class User {
String name;
String email;
}
10.4 Composition Over Inheritance
java
// Bad: Inheritance for code reuse
class Vehicle {
void start() { }
}
class FlyingCar extends Vehicle {
void fly() { }
}
// Good: Composition
class Engine {
void start() { }
}
class Wings {
void fly() { }
}
class FlyingCar {
private Engine engine;
private Wings wings;
void start() {
[Link]();
}
void fly() {
[Link]();
}
}
11. Access Modifiers
java
class Example {
public int publicVar; // Accessible everywhere
protected int protectedVar; // Accessible in package + subclasses
int defaultVar; // Accessible in package only
private int privateVar; // Accessible in class only
public void publicMethod() { }
protected void protectedMethod() { }
void defaultMethod() { }
private void privateMethod() { }
}
12. Constructors
java
class Person {
String name;
int age;
// Default constructor
Person() {
[Link] = "Unknown";
[Link] = 0;
}
// Parameterized constructor
Person(String name, int age) {
[Link] = name;
[Link] = age;
}
// Constructor chaining
Person(String name) {
this(name, 0); // Calls parameterized constructor
}
}
class Employee extends Person {
String company;
Employee(String name, int age, String company) {
super(name, age); // Call parent constructor
[Link] = company;
}
}
LinkedIn: Japneet Sachdeva
13. Static vs Instance
java
class Counter {
static int staticCount = 0; // Shared across all instances
int instanceCount = 0; // Unique to each instance
static void staticMethod() {
// Can access only static members
staticCount++;
}
void instanceMethod() {
// Can access both static and instance members
staticCount++;
instanceCount++;
}
}
// Usage
Counter c1 = new Counter();
Counter c2 = new Counter();
[Link]++; // Only c1's count increases
[Link]++; // Shared count increases
14. Final Keyword
java
// Final variable: Cannot be reassigned
final int MAX_SIZE = 100;
// Final method: Cannot be overridden
class Parent {
final void display() {
[Link]("Cannot override");
}
}
// Final class: Cannot be inherited
final class Utility {
// Cannot extend this class
}
15. Quick Reference: Choosing Between Abstractions
Decision Tree
1. Need multiple inheritance?
Yes → Interface
No → Continue
2. Need to maintain state (instance variables)?
Yes → Abstract Class
No → Continue
3. All methods have default implementation?
Yes → Regular Class or Interface with default methods
No → Continue
4. Defining a contract/capability?
Yes → Interface
No → Abstract Class
Common Patterns
Strategy Pattern: Use interfaces
Template Method: Use abstract classes
Plugin System: Use interfaces
Framework Base Classes: Use abstract classes
Summary
Core OOP Concepts:
1. Encapsulation: Bundle data + methods, hide internals
2. Inheritance: Reuse code from parent classes
3. Polymorphism: Same interface, different behaviors
4. Abstraction: Hide complexity, expose essentials
Key Principles:
SOLID: Five principles for maintainable code
DRY: Don't repeat yourself
KISS: Keep it simple
YAGNI: Build only what's needed
Composition over Inheritance: Prefer has-a over is-a
Modern Java (8+):
Interfaces can have default, static, and private methods
Blurs line between interfaces and abstract classes
Choose based on multiple inheritance needs and state requirements
LinkedIn: Japneet Sachdeva