LearnContact
Lesson 2450 min read

Abstraction in Java

Learn Abstraction in Java in detail, including abstract classes, abstract methods, concrete methods, constructors, fields, inheritance, polymorphism, interfaces, implementation hiding, and practical examples.

Introduction

Abstraction is one of the fundamental principles of Object-Oriented Programming. It focuses on exposing essential behavior while hiding unnecessary implementation details.

Simple Abstraction Example
abstract class Animal {

    abstract void sound();

}


class Dog extends Animal {

    @Override
    void sound() {

        System.out.println(
            "Dog barks"
        );

    }

}

The Animal class defines what every animal must be able to do, while the Dog class decides how that behavior is implemented.

What You Will Learn
  • What abstraction is.
  • Why abstraction is useful.
  • What implementation hiding means.
  • How Java achieves abstraction.
  • What abstract classes are.
  • How the abstract keyword works.
  • What abstract methods are.
  • What concrete methods are.
  • Rules of abstract classes and methods.
  • Why abstract classes cannot be instantiated.
  • How abstract class references work.
  • How inheritance supports abstraction.
  • How child classes implement abstract methods.
  • What partially abstract classes are.
  • How multilevel abstraction works.
  • How fields work in abstract classes.
  • How constructors work in abstract classes.
  • How static and final members work.
  • How access modifiers affect abstraction.
  • How abstraction supports polymorphism.
  • How abstract classes work with dynamic method dispatch.
  • How to use polymorphic arrays.
  • How abstract types work as parameters and return types.
  • What the Template Method Pattern is.
  • The difference between abstraction and encapsulation.
  • The difference between abstract classes and interfaces.
  • When abstract classes should be used.
  • When abstract classes should be avoided.

What is Abstraction?

Abstraction is the process of representing the essential features of something while hiding unnecessary implementation details. It describes what an object can do without requiring users of that object to understand every internal step.

Core Idea
USER SEES

        pay()

          │
          ▼

┌───────────────────────┐
│      ABSTRACTION      │
└───────────────────────┘

          │
          ▼

IMPLEMENTATION HIDDEN

Validate account
Connect to gateway
Authenticate payment
Process transaction
Handle response
Store transaction
Generate receipt
Abstraction in Simple Words
  • Show what is necessary.
  • Hide how the internal work is performed.
  • Expose simple operations.
  • Keep complex implementation details internal.
  • Allow implementations to change without affecting users.

Why Use Abstraction?

Simplicity

Users work with essential operations instead of internal complexity.

Implementation Hiding

Internal processing details remain hidden behind clear operations.

Flexibility

Implementations can change while the abstraction remains stable.

Extensibility

New implementations can follow the same common abstraction.

Loose Coupling

Code can depend on abstractions instead of concrete classes.

Maintainability

Complex systems become easier to organize and modify.

Real-World Analogy

When driving a car, the driver uses the steering wheel, accelerator, brake, and gear controls. The driver does not need to understand every internal engine operation.

Car Abstraction
DRIVER USES

start()

accelerate()

brake()

steer()


        │
        ▼

┌──────────────────────┐
│      CAR SYSTEM      │
└──────────────────────┘

        │
        ▼

HIDDEN INTERNAL DETAILS

Fuel injection
Ignition timing
Engine combustion
Transmission control
Brake hydraulics
Electronic systems

The controls form an abstraction. They expose essential operations while hiding complex implementation details.

Implementation Hiding

Implementation hiding means that calling code knows what operation is available but does not need to know every internal step used to perform that operation.

Simple Public Operation
payment.pay(5000);
Hidden Complexity
pay(5000)

    │
    ▼

Validate amount

    │
    ▼

Authenticate user

    │
    ▼

Connect to payment provider

    │
    ▼

Process transaction

    │
    ▼

Handle response

    │
    ▼

Store result

Ways to Achieve Abstraction in Java

Abstraction Tools
ABSTRACTION

├── Abstract Classes
│
│   ├── Abstract Methods
│   ├── Concrete Methods
│   ├── Fields
│   └── Constructors
│
└── Interfaces

    ├── Abstract Behavior
    ├── Multiple Implementations
    └── Capability Contracts
Main Java Abstraction Mechanisms
  • Abstract classes provide partial abstraction and shared implementation.
  • Interfaces define contracts that implementations agree to follow.
  • This lesson focuses primarily on abstract classes.
  • Interfaces are covered in the next lesson.

Abstract Classes

An abstract class is a class declared with the abstract keyword. It is designed to act as a base class and cannot be instantiated directly.

Abstract Class Syntax
abstract class ClassName {

    // Fields

    // Constructors

    // Abstract methods

    // Concrete methods

}
Example
abstract class Shape {

    abstract double area();

}

The abstract Keyword

The abstract keyword can be used with classes and methods.

Abstract Class
abstract class Animal {

}
Abstract Method
abstract void sound();
Meaning of abstract
  • An abstract class is incomplete by design.
  • An abstract method has no implementation in that class.
  • A concrete child class must complete required abstract behavior.
  • Abstract types are intended to be extended or implemented.

Basic Abstract Class Example

Animal.java
public abstract class Animal {

    public abstract void sound();


    public void sleep() {

        System.out.println(
            "Animal is sleeping"
        );

    }

}
Dog.java
public class Dog
        extends Animal {

    @Override
    public void sound() {

        System.out.println(
            "Dog barks"
        );

    }

}
Main.java
public class Main {

    public static void main(
        String[] args
    ) {

        Dog dog = new Dog();


        dog.sound();

        dog.sleep();

    }

}
Output
Dog barks

Animal is sleeping

Abstract Methods

An abstract method declares a method signature without providing a method body.

Abstract Method Syntax
abstract returnType methodName(
    parameters
);
Examples
abstract void start();


abstract double area();


abstract boolean pay(
    double amount
);
No Method Body
  • An abstract method ends with a semicolon.
  • It does not contain braces.
  • It does not provide an implementation.
  • A concrete child class must provide the required implementation.

Concrete Methods

An abstract class can contain normal methods with complete implementations. These are called concrete methods.

Concrete Method
abstract class Vehicle {

    public void stop() {

        System.out.println(
            "Vehicle stopped"
        );

    }

}

Child classes inherit the concrete method and can use it directly unless overriding is required.

Abstract and Concrete Methods Together

Partial Abstraction
abstract class Vehicle {

    abstract void start();


    void stop() {

        System.out.println(
            "Vehicle stopped"
        );

    }

}
Responsibility
ABSTRACT METHOD

start()

Child decides HOW



CONCRETE METHOD

stop()

Parent provides shared behavior

Rules of Abstract Methods

  • An abstract method has no method body.
  • An abstract method must be declared with the abstract keyword.
  • An abstract method ends with a semicolon.
  • A class containing an abstract method must be abstract.
  • A concrete child class must implement all inherited abstract methods.
  • An abstract child class may leave inherited abstract methods unimplemented.
  • Abstract methods cannot be private.
  • Abstract methods cannot be final.
  • Abstract methods cannot be static.
  • An overriding implementation must follow normal overriding rules.

Rules of Abstract Classes

  • An abstract class is declared with the abstract keyword.
  • An abstract class cannot be instantiated directly.
  • An abstract class can contain abstract methods.
  • An abstract class can contain concrete methods.
  • An abstract class can contain fields.
  • An abstract class can contain constructors.
  • An abstract class can contain static members.
  • An abstract class can contain final members.
  • An abstract class can contain no abstract methods.
  • An abstract class can extend another class.
  • A class can extend only one abstract or concrete class.
  • An abstract class can implement interfaces.
  • A concrete child must implement all remaining abstract methods.

Cannot Create Abstract Class Objects

Not Allowed
abstract class Animal {

}


Animal animal =
        new Animal();


// Compilation error

An abstract class represents an incomplete or general concept, so Java does not allow direct object creation.

Abstract Class References

Although an abstract class cannot be instantiated, it can be used as a reference type.

Abstract Reference
Animal animal =
        new Dog();


animal.sound();
Important Difference
  • Creating an abstract class object is not allowed.
  • Creating an abstract class reference is allowed.
  • The reference can point to a concrete child object.
  • This enables runtime polymorphism.

Abstract Classes and Inheritance

Inheritance Structure
       ABSTRACT CLASS

            Animal

       abstract sound()

            sleep()

               │
               │ extends
               ▼

        CONCRETE CLASS

              Dog

          sound() implemented

          sleep() inherited
Child Class
class Dog extends Animal {

    @Override
    void sound() {

        System.out.println(
            "Dog barks"
        );

    }

}

Implementing Abstract Methods

Abstract Parent
abstract class Shape {

    abstract double area();

}
Concrete Child
class Circle extends Shape {

    private final double radius;


    Circle(double radius) {

        this.radius = radius;

    }


    @Override
    double area() {

        return Math.PI
                * radius
                * radius;

    }

}

Partially Abstract Child Classes

An abstract child class does not have to implement every inherited abstract method. It can leave some behavior for a later concrete child class.

Abstract Parent
abstract class Device {

    abstract void start();

    abstract void stop();

}
Partially Implemented Child
abstract class Machine
        extends Device {

    @Override
    void stop() {

        System.out.println(
            "Machine stopped"
        );

    }

}
Concrete Child
class Robot extends Machine {

    @Override
    void start() {

        System.out.println(
            "Robot started"
        );

    }

}

Multilevel Abstraction

Abstraction Hierarchy
        Device

        abstract

           │
           ▼

        Machine

        abstract

           │
           ▼

         Robot

        concrete

Abstraction can be refined through multiple inheritance levels until a concrete class provides all required implementations.

Fields in Abstract Classes

Abstract classes can contain instance fields just like normal classes.

Abstract Class with Fields
abstract class Employee {

    private final String name;

    private double salary;


    Employee(
        String name,
        double salary
    ) {

        this.name = name;

        this.salary = salary;

    }


    public String getName() {

        return name;

    }


    public double getSalary() {

        return salary;

    }

}

Constructors in Abstract Classes

Abstract classes can have constructors. The constructor initializes the parent part of a child object.

Abstract Class Constructor
abstract class Animal {

    private final String name;


    Animal(String name) {

        this.name = name;

    }


    public String getName() {

        return name;

    }

}
Calling the Parent Constructor
class Dog extends Animal {

    Dog(String name) {

        super(name);

    }


    @Override
    void sound() {

        System.out.println(
            "Dog barks"
        );

    }

}

Constructor Execution Order

Constructor Example
abstract class Parent {

    Parent() {

        System.out.println(
            "Parent constructor"
        );

    }

}


class Child extends Parent {

    Child() {

        System.out.println(
            "Child constructor"
        );

    }

}
Execution Order
new Child()

     │
     ▼

Abstract Parent Constructor

     │
     ▼

Child Constructor

     │
     ▼

Object Ready
Why Does an Abstract Constructor Run?
  • The abstract class itself is not instantiated.
  • The concrete child object still contains inherited parent state.
  • The parent constructor initializes that state.
  • Parent construction happens before child construction.

Static Members in Abstract Classes

Static Member
abstract class Configuration {

    static final String VERSION =
            "1.0";


    static void showVersion() {

        System.out.println(
            VERSION
        );

    }

}
Using Static Members
Configuration.showVersion();

Final Members in Abstract Classes

Final Method
abstract class Payment {

    public final void validate(
        double amount
    ) {

        if (amount <= 0) {

            throw new IllegalArgumentException(
                "Invalid amount"
            );

        }

    }


    public abstract void pay(
        double amount
    );

}

A final concrete method can provide behavior that child classes are allowed to use but not override.

Access Modifiers in Abstract Classes

Allowed Access
ABSTRACT CLASS MEMBERS

public

protected

package-private

private


ABSTRACT METHODS

public

protected

package-private


NOT private

Because child classes
must be able to override them

Private Methods in Abstract Classes

An abstract class can contain private concrete methods. These methods can support shared internal logic but cannot be abstract or overridden.

Private Helper Method
abstract class Report {

    public void generate() {

        prepareData();

        createContent();

    }


    private void prepareData() {

        System.out.println(
            "Preparing data"
        );

    }


    protected abstract void
        createContent();

}

Abstract Classes and Polymorphism

Polymorphic References
Shape shape;


shape = new Circle(5);

System.out.println(
    shape.area()
);


shape = new Rectangle(
    10,
    5
);

System.out.println(
    shape.area()
);

The abstract Shape type provides a common abstraction while each concrete object provides its own area() implementation.

Dynamic Method Dispatch

Runtime Selection
Shape shape = new Circle(5);

        │
        ▼

Reference Type

Shape

        │
        ▼

Actual Object Type

Circle

        │
        ▼

shape.area()

        │
        ▼

Circle.area() Executes

Polymorphic Arrays

Array of Abstract References
Shape[] shapes = {

    new Circle(5),

    new Rectangle(10, 5),

    new Triangle(10, 4)

};
Processing All Shapes
for (Shape shape : shapes) {

    System.out.println(
        shape.area()
    );

}

Abstract Types as Method Parameters

General Parameter
static void printArea(
    Shape shape
) {

    System.out.println(
        shape.area()
    );

}
Different Objects
printArea(
    new Circle(5)
);


printArea(
    new Rectangle(10, 5)
);

Abstract Types as Return Types

Factory Method
static Shape createShape(
    String type
) {

    if (type.equals("circle")) {

        return new Circle(5);

    }


    return new Rectangle(
        10,
        5
    );

}
Using the Result
Shape shape =
        createShape("circle");


System.out.println(
    shape.area()
);

Template Method Pattern

An abstract class can define the overall sequence of an operation while allowing child classes to customize specific steps.

Report Template
abstract class Report {

    public final void generate() {

        fetchData();

        formatData();

        export();

    }


    protected void fetchData() {

        System.out.println(
            "Fetching data"
        );

    }


    protected abstract void
        formatData();


    protected void export() {

        System.out.println(
            "Exporting report"
        );

    }

}
PDF Report
class PDFReport extends Report {

    @Override
    protected void formatData() {

        System.out.println(
            "Formatting PDF"
        );

    }

}
Template Method Benefit
  • The parent controls the overall algorithm.
  • Child classes customize selected steps.
  • Shared behavior is not duplicated.
  • The final template method prevents the sequence from being changed.

Abstract Class vs Concrete Class

Comparison
ABSTRACT CLASS

Cannot be instantiated directly

May contain abstract methods

May contain concrete methods

Designed for extension

Can represent incomplete behavior



CONCRETE CLASS

Can be instantiated

Must provide complete required behavior

Creates actual objects

Can extend an abstract class

Abstraction vs Encapsulation

Comparison
ABSTRACTION

Focuses on WHAT an object does

Hides implementation complexity

Achieved using:

Abstract classes
Interfaces



ENCAPSULATION

Focuses on protecting object state

Controls access to data

Achieved using:

Classes
Private fields
Access modifiers
Controlled methods
Simple Difference
  • Abstraction hides complexity.
  • Encapsulation protects state and controls access.
  • The two principles often work together.

Abstraction vs Inheritance

Comparison
ABSTRACTION

Defines essential behavior

Hides implementation details

Answers:

WHAT should be done?



INHERITANCE

Creates parent-child relationships

Reuses and specializes behavior

Answers:

WHAT type is this?

Abstraction vs Polymorphism

Comparison
ABSTRACTION

Defines a common concept

Example:

Shape.area()



POLYMORPHISM

Allows different implementations

Example:

Circle.area()

Rectangle.area()

Triangle.area()

Abstract Class vs Interface

Comparison
ABSTRACT CLASS

A class can extend only one

Can have instance fields

Can have constructors

Can contain abstract methods

Can contain concrete methods

Useful for closely related classes



INTERFACE

A class can implement multiple

No normal instance state

No constructors

Defines capabilities and contracts

Can contain default and static methods

Useful for multiple implementations
Quick Decision
  • Use an abstract class when related classes share state and implementation.
  • Use an interface when different classes need to follow the same capability contract.
  • A class can extend one class and implement multiple interfaces.
  • Interfaces are covered fully in the next lesson.

When to Use Abstract Classes

  • When related classes share common state.
  • When related classes share common implementation.
  • When some behavior should be mandatory for child classes.
  • When some methods should have default implementations.
  • When constructors are needed for shared initialization.
  • When protected extension points are useful.
  • When a common algorithm contains customizable steps.
  • When the classes form a genuine IS-A hierarchy.

When to Avoid Abstract Classes

  • When unrelated classes only share a capability.
  • When multiple type inheritance is required.
  • When no shared state or implementation exists.
  • When composition provides greater flexibility.
  • When the hierarchy does not represent a genuine IS-A relationship.
  • When child classes would need to disable parent behavior.
  • When the abstraction creates unnecessary complexity.

Shape Example

Shape.java
public abstract class Shape {

    private final String color;


    public Shape(String color) {

        this.color = color;

    }


    public String getColor() {

        return color;

    }


    public abstract double area();


    public abstract double perimeter();


    public void display() {

        System.out.println(
            "Color: " + color
        );


        System.out.println(
            "Area: " + area()
        );


        System.out.println(
            "Perimeter: "
            + perimeter()
        );

    }

}
Circle.java
public class Circle
        extends Shape {

    private final double radius;


    public Circle(
        String color,
        double radius
    ) {

        super(color);

        this.radius = radius;

    }


    @Override
    public double area() {

        return Math.PI
                * radius
                * radius;

    }


    @Override
    public double perimeter() {

        return 2
                * Math.PI
                * radius;

    }

}

Employee Example

Employee.java
public abstract class Employee {

    private final int id;

    private final String name;


    public Employee(
        int id,
        String name
    ) {

        this.id = id;

        this.name = name;

    }


    public int getId() {

        return id;

    }


    public String getName() {

        return name;

    }


    public abstract double
        calculateSalary();


    public void displayDetails() {

        System.out.println(
            "ID: " + id
        );


        System.out.println(
            "Name: " + name
        );


        System.out.println(
            "Salary: ₹"
            + calculateSalary()
        );

    }

}
FullTimeEmployee.java
public class FullTimeEmployee
        extends Employee {

    private final double
        monthlySalary;


    public FullTimeEmployee(
        int id,
        String name,
        double monthlySalary
    ) {

        super(id, name);

        this.monthlySalary =
                monthlySalary;

    }


    @Override
    public double calculateSalary() {

        return monthlySalary;

    }

}
ContractEmployee.java
public class ContractEmployee
        extends Employee {

    private final double hourlyRate;

    private final int hoursWorked;


    public ContractEmployee(
        int id,
        String name,
        double hourlyRate,
        int hoursWorked
    ) {

        super(id, name);

        this.hourlyRate = hourlyRate;

        this.hoursWorked =
                hoursWorked;

    }


    @Override
    public double calculateSalary() {

        return hourlyRate
                * hoursWorked;

    }

}

Payment Example

Payment.java
public abstract class Payment {

    private final String
        transactionId;


    public Payment(
        String transactionId
    ) {

        this.transactionId =
                transactionId;

    }


    public String getTransactionId() {

        return transactionId;

    }


    protected void validateAmount(
        double amount
    ) {

        if (amount <= 0) {

            throw new IllegalArgumentException(
                "Amount must be positive"
            );

        }

    }


    public abstract boolean pay(
        double amount
    );

}
UPIPayment.java
public class UPIPayment
        extends Payment {

    private final String upiId;


    public UPIPayment(
        String transactionId,
        String upiId
    ) {

        super(transactionId);

        this.upiId = upiId;

    }


    @Override
    public boolean pay(
        double amount
    ) {

        validateAmount(amount);


        System.out.println(
            "Processing UPI payment"
        );


        System.out.println(
            "UPI ID: " + upiId
        );


        return true;

    }

}

Vehicle Example

Vehicle.java
public abstract class Vehicle {

    private final String brand;


    public Vehicle(String brand) {

        this.brand = brand;

    }


    public String getBrand() {

        return brand;

    }


    public abstract void start();


    public void stop() {

        System.out.println(
            brand + " stopped"
        );

    }

}
Car.java
public class Car extends Vehicle {

    public Car(String brand) {

        super(brand);

    }


    @Override
    public void start() {

        System.out.println(
            getBrand()
            + " car started"
        );

    }

}
ElectricCar.java
public class ElectricCar
        extends Vehicle {

    public ElectricCar(
        String brand
    ) {

        super(brand);

    }


    @Override
    public void start() {

        System.out.println(
            getBrand()
            + " electric motor started"
        );

    }

}

Bank Account Example

BankAccount.java
public abstract class BankAccount {

    private final String
        accountNumber;

    private double balance;


    public BankAccount(
        String accountNumber,
        double balance
    ) {

        this.accountNumber =
                accountNumber;

        this.balance = balance;

    }


    public double getBalance() {

        return balance;

    }


    public void deposit(
        double amount
    ) {

        if (amount > 0) {

            balance += amount;

        }

    }


    public abstract double
        calculateInterest();

}
SavingsAccount.java
public class SavingsAccount
        extends BankAccount {

    private final double
        interestRate;


    public SavingsAccount(
        String accountNumber,
        double balance,
        double interestRate
    ) {

        super(
            accountNumber,
            balance
        );


        this.interestRate =
                interestRate;

    }


    @Override
    public double calculateInterest() {

        return getBalance()
                * interestRate
                / 100;

    }

}

Notification Example

Notification.java
public abstract class Notification {

    private final String recipient;


    public Notification(
        String recipient
    ) {

        this.recipient = recipient;

    }


    public String getRecipient() {

        return recipient;

    }


    public final void notifyUser(
        String message
    ) {

        validate(message);

        send(message);

        log();

    }


    private void validate(
        String message
    ) {

        if (
            message == null ||
            message.isBlank()
        ) {

            throw new IllegalArgumentException(
                "Message is required"
            );

        }

    }


    protected abstract void send(
        String message
    );


    private void log() {

        System.out.println(
            "Notification logged"
        );

    }

}
EmailNotification.java
public class EmailNotification
        extends Notification {

    public EmailNotification(
        String recipient
    ) {

        super(recipient);

    }


    @Override
    protected void send(
        String message
    ) {

        System.out.println(
            "Email sent to "
            + getRecipient()
        );

    }

}

Common Abstraction Errors

Common Errors
ABSTRACTION ERRORS

├── Trying to Instantiate an Abstract Class
├── Forgetting the abstract Keyword
├── Giving an Abstract Method a Body
├── Forgetting the Semicolon After Abstract Method
├── Declaring Abstract Method in Concrete Class
├── Not Implementing All Abstract Methods
├── Forgetting to Make Partial Child Abstract
├── Trying to Make Abstract Method private
├── Trying to Make Abstract Method final
├── Trying to Make Abstract Method static
├── Confusing Abstract Class with Interface
├── Assuming Abstract Class Cannot Have Constructors
├── Assuming Abstract Class Cannot Have Fields
├── Assuming Abstract Class Can Only Have Abstract Methods
├── Assuming Abstract Class Must Have Abstract Methods
├── Trying to Create Multiple Class Inheritance
├── Forgetting super() Constructor Rules
├── Calling Overridable Methods from Constructors
├── Exposing Mutable Fields Directly
├── Using protected Fields Unnecessarily
├── Creating Abstract Classes Without Clear Purpose
├── Using Abstraction for Unrelated Classes
├── Creating Deep Abstract Hierarchies
├── Breaking Parent Contracts
├── Child Classes Disabling Required Behavior
├── Throwing UnsupportedOperationException for Core Operations
├── Confusing Abstraction with Encapsulation
├── Confusing Abstraction with Inheritance
├── Confusing Abstraction with Polymorphism
├── Depending on Concrete Classes
├── Leaking Implementation Details
├── Creating God Abstract Classes
├── Putting Too Many Responsibilities in Base Class
├── Forcing Unrelated Methods on Children
├── Overusing Abstract Classes
├── Ignoring Interfaces
├── Ignoring Composition
├── Creating Fragile Parent-Child Coupling
├── Making Every Method Abstract
├── Making Every Method Concrete
├── Poor Access Modifier Selection
├── Forgetting @Override
├── Changing Method Signature Accidentally
├── Reducing Visibility in Implementations
├── Excessive Downcasting
├── Repeated Type Checking
├── Exposing Internal Algorithms
├── Unstable Abstractions
├── Poorly Named Abstract Types
└── Abstracting Too Early

Best Practices

  • Use abstraction to expose essential behavior.
  • Hide unnecessary implementation details.
  • Create abstractions around stable concepts.
  • Use meaningful abstract class names.
  • Use abstract classes for genuine IS-A relationships.
  • Keep abstract classes focused.
  • Avoid God abstract classes.
  • Use abstract methods only for behavior that must vary.
  • Provide concrete methods for genuinely shared behavior.
  • Keep fields private whenever possible.
  • Use protected methods as controlled extension points.
  • Avoid protected mutable fields.
  • Use constructors for required shared state.
  • Validate constructor arguments.
  • Use final fields for immutable shared state when appropriate.
  • Use @Override for every implemented abstract method.
  • Keep child behavior compatible with the parent contract.
  • Do not weaken expected behavior in child classes.
  • Keep inheritance hierarchies shallow.
  • Use abstract references for polymorphic code.
  • Accept abstract types as method parameters.
  • Return abstract types when implementation details are unnecessary.
  • Use polymorphic collections for related implementations.
  • Avoid unnecessary downcasting.
  • Avoid repeated instanceof checks.
  • Use the Template Method Pattern for stable algorithms with customizable steps.
  • Make template methods final when the execution sequence must remain fixed.
  • Keep customizable steps protected when they are implementation details.
  • Use private helper methods for internal shared logic.
  • Do not call overridable methods from constructors unless carefully designed.
  • Prefer interfaces for unrelated classes sharing capabilities.
  • Prefer interfaces when multiple type inheritance is required.
  • Prefer composition when behavior must be replaceable dynamically.
  • Do not use abstraction only because it is an OOP feature.
  • Avoid premature abstraction.
  • Create abstractions after identifying genuine common behavior.
  • Keep public contracts small and clear.
  • Hide implementation details that callers do not need.
  • Allow implementations to change without affecting calling code.
  • Test concrete implementations through abstract references.
  • Document important abstract method contracts.
  • Define valid input and output expectations.
  • Define exception behavior clearly.
  • Keep abstractions cohesive.
  • Use abstraction to reduce coupling.
  • Avoid leaking concrete implementation types.
  • Combine abstraction with encapsulation.
  • Combine abstraction with polymorphism.
  • Design for maintainability.
  • Keep the abstraction simpler than the implementation it hides.

Common Misconceptions

Avoid These Misconceptions
  • Abstraction does not mean only abstract classes.
  • Interfaces also provide abstraction.
  • An abstract class can have constructors.
  • An abstract class can have fields.
  • An abstract class can have concrete methods.
  • An abstract class can have static methods.
  • An abstract class can have final methods.
  • An abstract class does not need to contain an abstract method.
  • A class with an abstract method must be abstract.
  • An abstract class cannot be instantiated directly.
  • An abstract class can be used as a reference type.
  • Abstract methods do not have method bodies.
  • Abstract methods cannot be private.
  • Abstract methods cannot be final.
  • Abstract methods cannot be static.
  • A concrete child must implement all inherited abstract methods.
  • An abstract child may leave abstract methods unimplemented.
  • Abstract class constructors execute during child object creation.
  • Abstraction and encapsulation are different principles.
  • Abstraction and inheritance are different principles.
  • Abstraction and polymorphism are different principles.
  • Abstract classes and interfaces are not identical.
  • A class can extend only one abstract or concrete class.
  • A class can implement multiple interfaces.
  • Abstraction does not automatically create good design.
  • More abstract classes do not mean better architecture.
  • Deep abstraction hierarchies can become difficult to maintain.
  • Not every shared method requires an abstract parent class.
  • Composition may be better than inheritance.
  • Good abstraction hides complexity behind a stable contract.

Practice Exercises

Exercise 1: Shape Hierarchy
  • Create an abstract Shape class.
  • Add abstract area() and perimeter() methods.
  • Create Circle and Rectangle classes.
  • Implement all abstract methods.
  • Process objects through Shape references.
Exercise 2: Employee Payroll
  • Create an abstract Employee class.
  • Store common employee data.
  • Create an abstract calculateSalary() method.
  • Create FullTimeEmployee and ContractEmployee.
  • Calculate salaries polymorphically.
Exercise 3: Vehicle System
  • Create an abstract Vehicle class.
  • Add shared brand information.
  • Create an abstract start() method.
  • Create concrete stop() behavior.
  • Implement Car and Motorcycle.
Exercise 4: Bank Accounts
  • Create an abstract BankAccount class.
  • Add shared balance behavior.
  • Create an abstract calculateInterest() method.
  • Create SavingsAccount and FixedDepositAccount.
  • Process all accounts through abstract references.
Exercise 5: Report Generator
  • Create an abstract Report class.
  • Create a final generate() template method.
  • Add common data-loading logic.
  • Create an abstract formatting step.
  • Implement PDFReport and CSVReport.
Exercise 6: Payment System
  • Create an abstract Payment class.
  • Add common transaction information.
  • Create shared amount validation.
  • Create an abstract pay() method.
  • Implement CardPayment and UPIPayment.
Exercise 7: Notification System
  • Create an abstract Notification class.
  • Create a final notification workflow.
  • Add shared validation and logging.
  • Create an abstract send() step.
  • Implement Email and SMS notifications.
Exercise 8: Abstract Design Review
  • Choose an existing class hierarchy.
  • Identify common state.
  • Identify common behavior.
  • Identify behavior that varies.
  • Decide whether an abstract class, interface, or composition is best.

Common Interview Questions

What is abstraction in Java?

Abstraction exposes essential behavior while hiding unnecessary implementation details.

How is abstraction achieved in Java?

Abstraction is mainly achieved using abstract classes and interfaces.

What is an abstract class?

An abstract class is a class declared with the abstract keyword that cannot be instantiated directly.

What is an abstract method?

An abstract method declares a method signature without providing a method body.

Can an abstract class have a constructor?

Yes. Its constructor initializes the parent part of concrete child objects.

Can an abstract class have concrete methods?

Yes.

Can an abstract class have fields?

Yes.

Can an abstract class have no abstract methods?

Yes.

Can an abstract class be instantiated?

No.

Can an abstract class be used as a reference type?

Yes. It can refer to objects of concrete child classes.

Can an abstract method be private?

No, because a child class must be able to override it.

Can an abstract method be final?

No. Abstract requires implementation while final prevents overriding.

Can an abstract method be static?

No. Static methods do not participate in instance-method overriding.

What is the difference between abstraction and encapsulation?

Abstraction hides implementation complexity, while encapsulation protects state and controls access.

What is the difference between an abstract class and an interface?

An abstract class can provide shared state, constructors, and implementation, while an interface primarily defines a capability contract that multiple classes can implement.

Frequently Asked Questions

Why use an abstract class instead of a normal class?

Use an abstract class when the base concept should not be instantiated directly and child classes must provide specific behavior.

Why can an abstract class have a constructor?

The constructor initializes shared state inherited by concrete child objects.

Can one abstract class extend another abstract class?

Yes.

Does an abstract child need to implement every abstract method?

No. It may leave methods unimplemented for later concrete child classes.

Can a concrete child leave an abstract method unimplemented?

No. A concrete class must implement all remaining inherited abstract methods.

Should every parent class be abstract?

No. A class should be abstract only when the design represents an incomplete base concept or requires child-specific implementation.

What should I learn after Abstraction?

The next lesson covers Interfaces in Java.

Key Takeaways

  • Abstraction is a fundamental Object-Oriented Programming principle.
  • Abstraction exposes essential behavior.
  • Abstraction hides unnecessary implementation details.
  • Abstraction focuses on what an object does.
  • Abstract classes and interfaces are the main abstraction mechanisms in Java.
  • An abstract class is declared using the abstract keyword.
  • An abstract class cannot be instantiated directly.
  • An abstract class can be used as a reference type.
  • An abstract method has no method body.
  • An abstract method ends with a semicolon.
  • A class containing an abstract method must be abstract.
  • A concrete child must implement all remaining abstract methods.
  • An abstract child can leave methods unimplemented.
  • Abstract methods cannot be private.
  • Abstract methods cannot be final.
  • Abstract methods cannot be static.
  • An abstract class can contain concrete methods.
  • An abstract class can contain fields.
  • An abstract class can contain constructors.
  • An abstract class can contain static members.
  • An abstract class can contain final members.
  • An abstract class can contain private concrete methods.
  • An abstract class does not need to contain abstract methods.
  • Abstract class constructors initialize inherited state.
  • Parent constructors execute before child constructors.
  • Abstract classes support inheritance.
  • Abstract classes support runtime polymorphism.
  • One abstract reference can represent different concrete objects.
  • Dynamic method dispatch selects the correct implementation.
  • Abstract types can be used as array element types.
  • Abstract types can be used as method parameters.
  • Abstract types can be used as method return types.
  • The Template Method Pattern defines a common algorithm with customizable steps.
  • Abstraction and encapsulation are different principles.
  • Abstraction hides complexity.
  • Encapsulation protects state.
  • Inheritance creates type relationships.
  • Polymorphism provides multiple implementations.
  • Abstract classes are useful when related classes share state.
  • Abstract classes are useful when related classes share implementation.
  • Interfaces are useful for common capabilities.
  • A class can extend only one class.
  • A class can implement multiple interfaces.
  • Good abstractions should remain focused.
  • Good abstractions should expose stable contracts.
  • Deep abstract hierarchies should be avoided.
  • Protected mutable fields should generally be avoided.
  • Private fields preserve encapsulation.
  • Protected methods can provide controlled extension points.
  • Composition should be considered when inheritance is not appropriate.
  • Abstraction should simplify the use of complex systems.
  • Good abstraction reduces coupling.
  • Good abstraction improves extensibility.
  • Good abstraction allows implementation details to change independently.

Summary

Abstraction is the process of exposing essential behavior while hiding unnecessary implementation details. It allows users of a class to focus on what an operation does instead of every internal step used to perform it.

Java mainly achieves abstraction through abstract classes and interfaces. Abstract classes are declared with the abstract keyword and are designed to act as incomplete base classes.

An abstract method declares required behavior without providing an implementation. Concrete child classes must implement all inherited abstract methods, while abstract child classes may leave some methods for later subclasses.

Abstract classes can contain fields, constructors, concrete methods, static members, final members, and private helper methods. This allows them to combine shared implementation with required child-specific behavior.

Although an abstract class cannot be instantiated directly, it can be used as a reference type. This allows different concrete child objects to be processed through a common abstraction and supports runtime polymorphism.

The Template Method Pattern is an important use of abstract classes. A parent class defines the overall algorithm while child classes customize selected steps.

Abstraction differs from encapsulation. Abstraction hides complexity and focuses on essential operations, while encapsulation protects object state and controls access to data.

Good abstraction uses focused contracts, genuine type relationships, controlled extension points, private state, shallow hierarchies, and the correct balance between abstract classes, interfaces, and composition.

Lesson 24 Completed
  • You understand what abstraction is.
  • You understand why abstraction is useful.
  • You understand implementation hiding.
  • You know how Java achieves abstraction.
  • You understand abstract classes.
  • You can use the abstract keyword.
  • You understand abstract methods.
  • You understand concrete methods.
  • You know abstract method rules.
  • You know abstract class rules.
  • You understand why abstract classes cannot be instantiated.
  • You can use abstract class references.
  • You understand abstraction and inheritance.
  • You can implement abstract methods.
  • You understand partially abstract child classes.
  • You understand multilevel abstraction.
  • You understand fields in abstract classes.
  • You understand constructors in abstract classes.
  • You understand constructor execution order.
  • You understand static members.
  • You understand final members.
  • You understand access modifiers.
  • You understand private helper methods.
  • You understand abstraction and polymorphism.
  • You understand dynamic method dispatch.
  • You can create polymorphic arrays.
  • You can use abstract types as parameters.
  • You can use abstract types as return types.
  • You understand the Template Method Pattern.
  • You know the difference between abstract and concrete classes.
  • You know the difference between abstraction and encapsulation.
  • You know the difference between abstraction and inheritance.
  • You know the difference between abstraction and polymorphism.
  • You understand the difference between abstract classes and interfaces.
  • You know when to use abstract classes.
  • You know when to avoid abstract classes.
  • You can design practical abstractions.
  • You can identify common abstraction errors.
  • You know abstraction best practices.
  • You are ready to learn Interfaces in Java.
Next Lesson →

Interfaces in Java