Java Tutorial 0/145 lessons ~6 min read Lesson 22

    Abstraction

    java abstraction abstract class interface default method static functional interface dependency injection spring abstract vs interface

    Course progress0%
    Focus
    24 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    In the previous lessons, you learned about Encapsulation, Inheritance, and Polymorphism. Together, these concepts help build reusable and maintainable software.

    However, imagine you're designing an online payment system.

    Users only need to know:

    • Enter the amount
    • Choose a payment method
    • Click Pay

    They do not need to know:

    • How the payment gateway encrypts data
    • How the bank verifies the transaction
    • How the server communicates with third-party APIs
    • How the database stores transaction records

    The internal implementation is hidden from the user.

    This concept is called Abstraction.

    Abstraction is one of the four fundamental pillars of Object-Oriented Programming (OOP).

    It focuses on hiding implementation details and exposing only the essential functionality.

    Java provides abstraction through:

    • Abstract Classes
    • Interfaces

    Abstraction is widely used in:

    • Spring Boot
    • Hibernate
    • JDBC
    • Java Collections Framework
    • Microservices
    • REST APIs
    • Design Patterns
    • Enterprise Applications

    In this lesson, you'll learn:

    • What is Abstraction?
    • Why Abstraction is Important
    • Abstract Classes
    • Abstract Methods
    • Concrete Methods
    • Interfaces
    • Default Methods
    • Static Interface Methods
    • Functional Interfaces
    • Multiple Inheritance using Interfaces
    • Dependency Injection Concepts
    • Real-world Examples
    • Best Practices
    • Common Mistakes
    • Hands-on Exercises
    • Professional Interview Questions

    What is Abstraction?

    Abstraction is the process of hiding implementation details and exposing only the necessary functionality.

    Example:

    Driving a car.

    The driver uses:

    • Steering Wheel
    • Brake
    • Accelerator
    • Gear

    The driver does not need to understand:

    • Engine combustion
    • Fuel injection
    • Transmission mechanics

    Only the essential controls are visible.

    Similarly, in Java:

    User
    Interface
    Hidden Implementation

    Why Abstraction?

    Without abstraction:

    java
    Payment payment = new Payment();
    payment.connectBank();
    payment.encrypt();
    payment.verifyOTP();
    payment.updateDatabase();
    payment.generateReceipt();

    With abstraction:

    java
    payment.pay();

    Benefits:

    • Hides complexity
    • Reduces coupling
    • Easier maintenance
    • Better security
    • Improved flexibility
    • Easier testing

    Abstract Class

    An abstract class is a class that cannot be instantiated directly.

    Example:

    java
    abstract class Animal {
    }

    This is invalid:

    java
    Animal animal = new Animal();

    Compilation Error.

    An abstract class is designed to be extended.

    Abstract Methods

    An abstract method has no implementation.

    Example:

    java
    abstract class Animal {
    abstract void sound();
    }

    The child class must provide the implementation.

    Implementing Abstract Methods

    java
    abstract class Animal {
    abstract void sound();
    }
    class Dog extends Animal {
    @Override
    void sound() {
    System.out.println("Dog Barks");
    }
    }

    Using it:

    java
    Animal animal = new Dog();
    animal.sound();

    Output:

    Dog Barks

    Concrete Methods

    Abstract classes can also contain fully implemented methods.

    Example:

    java
    abstract class Animal {
    void eat() {
    System.out.println("Eating...");
    }
    abstract void sound();
    }

    Child classes inherit the concrete method while implementing the abstract one.

    When Should You Use an Abstract Class?

    Use an abstract class when:

    • Multiple classes share common code.
    • Some methods have identical implementations.
    • Other methods require different implementations.
    • You want to provide shared state (fields).

    Example:

    Vehicle
    Car
    Bus
    Truck

    What is an Interface?

    An interface defines a contract that classes agree to implement.

    Example:

    java
    interface Payment {
    void pay();
    }

    Implementing:

    java
    class UpiPayment implements Payment {
    @Override
    public void pay() {
    System.out.println("UPI Payment");
    }
    }

    Using:

    java
    Payment payment = new UpiPayment();
    payment.pay();

    Output:

    UPI Payment

    Abstract Class vs Interface

    Abstract ClassInterface
    Uses extendsUses implements
    Can have constructorsCannot have constructors
    Can have instance variablesOnly constants (public static final)
    Can contain abstract and concrete methodsCan contain abstract, default, static, and private methods (Java 9+)
    Supports single inheritanceA class can implement multiple interfaces

    Default Methods (Java 8+)

    Interfaces can provide default implementations.

    java
    interface Vehicle {
    default void start() {
    System.out.println("Vehicle Started");
    }
    }

    The implementing class may use or override this behavior.

    Static Methods in Interfaces

    java
    interface Calculator {
    static int square(int number) {
    return number * number;
    }
    }

    Calling:

    java
    System.out.println(Calculator.square(5));

    Output:

    25

    Functional Interfaces

    A Functional Interface contains exactly one abstract method.

    Example:

    java
    @FunctionalInterface
    interface Greeting {
    void sayHello();
    }

    Functional interfaces are the foundation of:

    • Lambda Expressions
    • Streams API
    • Method References

    Common examples:

    • Runnable
    • Callable
    • Comparator
    • Predicate
    • Function
    • Consumer
    • Supplier

    Multiple Inheritance Using Interfaces

    Java does not allow multiple inheritance with classes.

    However:

    java
    interface Printer {
    void print();
    }
    interface Scanner {
    void scan();
    }
    class MultiFunctionPrinter implements Printer, Scanner {
    public void print() {
    System.out.println("Printing...");
    }
    public void scan() {
    System.out.println("Scanning...");
    }
    }

    This avoids the Diamond Problem associated with multiple inheritance of classes.

    Dependency Injection Concept

    One of the biggest advantages of abstraction is Dependency Injection.

    Example:

    java
    interface NotificationService {
    void send(String message);
    }

    Implementations:

    java
    class EmailService implements NotificationService {
    public void send(String message) {
    System.out.println("Sending Email: " + message);
    }
    }
    class SmsService implements NotificationService {
    public void send(String message) {
    System.out.println("Sending SMS: " + message);
    }
    }

    Using abstraction:

    java
    NotificationService service = new EmailService();
    service.send("Welcome!");

    Changing to SMS requires only:

    java
    service = new SmsService();

    The client code remains unchanged.

    This principle is heavily used by the Spring Framework.

    Real-World Example: Banking Application

    java
    abstract class Account {
    abstract double calculateInterest(double balance);
    }

    Implementations:

    java
    class SavingsAccount extends Account {
    @Override
    double calculateInterest(double balance) {
    return balance * 0.05;
    }
    }
    class CurrentAccount extends Account {
    @Override
    double calculateInterest(double balance) {
    return 0;
    }
    }

    Real-World Example: Payment Gateway

    java
    interface PaymentGateway {
    void processPayment(double amount);
    }

    Implementations:

    • RazorpayPayment
    • StripePayment
    • PayPalPayment

    Each class provides its own implementation while exposing the same contract.

    Memory Representation

    java
    Payment payment = new UpiPayment();

    Memory:

    Stack
    payment
    Heap
    +---------------------------+
    | UpiPayment Object |
    +---------------------------+

    Reference Type:

    Payment

    Actual Object:

    UpiPayment

    The actual implementation is selected at runtime.

    Best Practices

    Program to Interfaces

    Prefer:

    java
    List<String> names = new ArrayList<>();

    Instead of:

    java
    ArrayList<String> names = new ArrayList<>();

    Use Abstract Classes for Shared State

    If multiple classes share fields and common implementations, use an abstract class.

    Use Interfaces for Contracts

    Interfaces define capabilities that unrelated classes can implement.

    Keep Interfaces Focused

    Follow the Interface Segregation Principle (ISP) by designing small, purpose-specific interfaces.

    Favor Composition with Abstraction

    Use interfaces to reduce coupling and improve testability.

    Common Mistakes

    Creating Large Interfaces

    Large interfaces force implementing classes to define methods they may not need.

    Using Abstract Classes When No Shared Code Exists

    If only behavior needs to be defined, an interface is often a better choice.

    Forgetting to Implement Abstract Methods

    A non-abstract subclass must implement all inherited abstract methods.

    Confusing Abstraction with Encapsulation

    • Abstraction hides implementation details.
    • Encapsulation protects internal data.

    Depending on Concrete Classes

    Coding against concrete implementations reduces flexibility.

    Hands-on Exercise

    Create a Java program that:

    1. Creates an abstract class Employee with:
      • Fields: name, employeeId
      • Concrete method: displayInfo()
      • Abstract method: calculateSalary()
    2. Creates FullTimeEmployee and ContractEmployee classes that extend Employee.
    3. Creates a NotificationService interface.
    4. Implements it using EmailNotification and SmsNotification.
    5. Demonstrates runtime polymorphism using interface references.
    6. Adds a default method to the interface.
    7. Uses a functional interface with a lambda expression to print a welcome message.

    Summary

    Abstraction simplifies complex systems by exposing only essential functionality while hiding implementation details. Java supports abstraction using abstract classes and interfaces. Abstract classes are useful when sharing common state and behavior, whereas interfaces define contracts that enable loose coupling, multiple inheritance of type, and highly extensible enterprise applications.

    Key Takeaways

    • Abstraction hides implementation details and exposes essential functionality.
    • Abstract classes cannot be instantiated.
    • Abstract methods must be implemented by concrete subclasses.
    • Interfaces define contracts for implementing classes.
    • Interfaces support multiple inheritance of type.
    • Default and static methods enhance interface capabilities.
    • Functional interfaces enable lambda expressions.
    • Programming to interfaces improves flexibility and maintainability.
    • Abstraction is the foundation of Dependency Injection in frameworks like Spring.

    Professional Interview Questions

    1What is Abstraction in Java?

    Professional Answer

    Abstraction is an Object-Oriented Programming principle that hides implementation details while exposing only the essential functionality required by clients. It simplifies application design, reduces complexity, and promotes loose coupling. Java achieves abstraction through abstract classes and interfaces.

    Follow-up Questions

    • Which Java constructs support abstraction?
    • How does abstraction improve maintainability?

    Interview Tip: Remember: Abstraction = Hide the implementation, Encapsulation = Protect the data.

    2What is the difference between an Abstract Class and an Interface?

    Professional Answer

    An abstract class is suitable when related classes need to share common state, constructors, and partially implemented behavior. An interface defines a contract that unrelated classes can implement. A class can extend only one abstract class but can implement multiple interfaces, making interfaces the preferred choice for defining capabilities and enabling loose coupling.

    Follow-up Questions

    • When should you choose an interface over an abstract class?
    • Can an interface contain implemented methods?

    Interview Tip: Use an abstract class for shared implementation and an interface for shared behavior or capabilities.

    3Why are Interfaces widely used in Spring Boot?

    Professional Answer

    Spring Boot promotes programming to interfaces because it enables loose coupling, dependency injection, easier unit testing, and flexible implementation replacement. Client code depends on abstractions rather than concrete classes, allowing implementations to change without affecting business logic.

    Follow-up Questions

    • How does Dependency Injection benefit from interfaces?
    • Can Spring inject multiple implementations of the same interface?

    Interview Tip: Business components depend on UserService rather than UserServiceImpl — interface UserService { ... } class UserServiceImpl implements UserService { ... }

    Ready to mark this lesson complete?Track your journey across the entire course.