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.
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 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.
USER SEES
pay()
│
▼
┌───────────────────────┐
│ ABSTRACTION │
└───────────────────────┘
│
▼
IMPLEMENTATION HIDDEN
Validate account
Connect to gateway
Authenticate payment
Process transaction
Handle response
Store transaction
Generate receipt- 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.
DRIVER USES
start()
accelerate()
brake()
steer()
│
▼
┌──────────────────────┐
│ CAR SYSTEM │
└──────────────────────┘
│
▼
HIDDEN INTERNAL DETAILS
Fuel injection
Ignition timing
Engine combustion
Transmission control
Brake hydraulics
Electronic systemsThe 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.
payment.pay(5000);pay(5000)
│
▼
Validate amount
│
▼
Authenticate user
│
▼
Connect to payment provider
│
▼
Process transaction
│
▼
Handle response
│
▼
Store resultWays to Achieve Abstraction in Java
ABSTRACTION
├── Abstract Classes
│
│ ├── Abstract Methods
│ ├── Concrete Methods
│ ├── Fields
│ └── Constructors
│
└── Interfaces
├── Abstract Behavior
├── Multiple Implementations
└── Capability Contracts- 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 ClassName {
// Fields
// Constructors
// Abstract methods
// Concrete methods
}abstract class Shape {
abstract double area();
}The abstract Keyword
The abstract keyword can be used with classes and methods.
abstract class Animal {
}abstract void sound();- 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
public abstract class Animal {
public abstract void sound();
public void sleep() {
System.out.println(
"Animal is sleeping"
);
}
}public class Dog
extends Animal {
@Override
public void sound() {
System.out.println(
"Dog barks"
);
}
}public class Main {
public static void main(
String[] args
) {
Dog dog = new Dog();
dog.sound();
dog.sleep();
}
}Dog barks
Animal is sleepingAbstract Methods
An abstract method declares a method signature without providing a method body.
abstract returnType methodName(
parameters
);abstract void start();
abstract double area();
abstract boolean pay(
double amount
);- 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.
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
abstract class Vehicle {
abstract void start();
void stop() {
System.out.println(
"Vehicle stopped"
);
}
}ABSTRACT METHOD
start()
Child decides HOW
CONCRETE METHOD
stop()
Parent provides shared behaviorRules 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
abstract class Animal {
}
Animal animal =
new Animal();
// Compilation errorAn 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.
Animal animal =
new Dog();
animal.sound();- 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
ABSTRACT CLASS
Animal
abstract sound()
sleep()
│
│ extends
▼
CONCRETE CLASS
Dog
sound() implemented
sleep() inheritedclass Dog extends Animal {
@Override
void sound() {
System.out.println(
"Dog barks"
);
}
}Implementing Abstract Methods
abstract class Shape {
abstract double area();
}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 class Device {
abstract void start();
abstract void stop();
}abstract class Machine
extends Device {
@Override
void stop() {
System.out.println(
"Machine stopped"
);
}
}class Robot extends Machine {
@Override
void start() {
System.out.println(
"Robot started"
);
}
}Multilevel Abstraction
Device
abstract
│
▼
Machine
abstract
│
▼
Robot
concreteAbstraction 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 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 Animal {
private final String name;
Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}class Dog extends Animal {
Dog(String name) {
super(name);
}
@Override
void sound() {
System.out.println(
"Dog barks"
);
}
}Constructor Execution Order
abstract class Parent {
Parent() {
System.out.println(
"Parent constructor"
);
}
}
class Child extends Parent {
Child() {
System.out.println(
"Child constructor"
);
}
}new Child()
│
▼
Abstract Parent Constructor
│
▼
Child Constructor
│
▼
Object Ready- 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
abstract class Configuration {
static final String VERSION =
"1.0";
static void showVersion() {
System.out.println(
VERSION
);
}
}Configuration.showVersion();Final Members in Abstract Classes
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
ABSTRACT CLASS MEMBERS
public
protected
package-private
private
ABSTRACT METHODS
public
protected
package-private
NOT private
Because child classes
must be able to override themPrivate 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.
abstract class Report {
public void generate() {
prepareData();
createContent();
}
private void prepareData() {
System.out.println(
"Preparing data"
);
}
protected abstract void
createContent();
}Abstract Classes and Polymorphism
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
Shape shape = new Circle(5);
│
▼
Reference Type
Shape
│
▼
Actual Object Type
Circle
│
▼
shape.area()
│
▼
Circle.area() ExecutesPolymorphic Arrays
Shape[] shapes = {
new Circle(5),
new Rectangle(10, 5),
new Triangle(10, 4)
};for (Shape shape : shapes) {
System.out.println(
shape.area()
);
}Abstract Types as Method Parameters
static void printArea(
Shape shape
) {
System.out.println(
shape.area()
);
}printArea(
new Circle(5)
);
printArea(
new Rectangle(10, 5)
);Abstract Types as Return Types
static Shape createShape(
String type
) {
if (type.equals("circle")) {
return new Circle(5);
}
return new Rectangle(
10,
5
);
}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.
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"
);
}
}class PDFReport extends Report {
@Override
protected void formatData() {
System.out.println(
"Formatting PDF"
);
}
}- 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
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 classAbstraction vs Encapsulation
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- Abstraction hides complexity.
- Encapsulation protects state and controls access.
- The two principles often work together.
Abstraction vs Inheritance
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
ABSTRACTION
Defines a common concept
Example:
Shape.area()
POLYMORPHISM
Allows different implementations
Example:
Circle.area()
Rectangle.area()
Triangle.area()Abstract Class vs Interface
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- 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
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()
);
}
}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
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()
);
}
}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;
}
}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
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
);
}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
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"
);
}
}public class Car extends Vehicle {
public Car(String brand) {
super(brand);
}
@Override
public void start() {
System.out.println(
getBrand()
+ " car started"
);
}
}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
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();
}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
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"
);
}
}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
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 EarlyBest 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
- 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
- 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.
- Create an abstract Employee class.
- Store common employee data.
- Create an abstract calculateSalary() method.
- Create FullTimeEmployee and ContractEmployee.
- Calculate salaries polymorphically.
- Create an abstract Vehicle class.
- Add shared brand information.
- Create an abstract start() method.
- Create concrete stop() behavior.
- Implement Car and Motorcycle.
- Create an abstract BankAccount class.
- Add shared balance behavior.
- Create an abstract calculateInterest() method.
- Create SavingsAccount and FixedDepositAccount.
- Process all accounts through abstract references.
- 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.
- Create an abstract Payment class.
- Add common transaction information.
- Create shared amount validation.
- Create an abstract pay() method.
- Implement CardPayment and UPIPayment.
- 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.
- 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.
- 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.