Back

What is Abstraction in Java?

30 Jan 2025
5 min read

Abstraction in Java is a basic concept in object-oriented programming (OOP) that focuses on presenting only the essential details of an object or system while hiding the underlying implementation details and complexities. But what is abstraction in Java, really? 

It allows developers to work with simplified representations of objects, which makes it easier to design robust, maintainable, and reusable code without being bogged down by implementation specifics.

Abstraction in Java allows you to design systems that highlight what an object does rather than how it does it. This feature improves the usability and clarity of the code. For example, when you use a smartphone, you interact with its touch screen and buttons without needing to understand the circuitry or software operating it. 

Similarly, abstraction in Java helps you interact with classes and methods without dealing with their internal implementation details. Developers achieve data abstraction in Java through abstract classes and interfaces. These tools allow you to define behaviors that classes must implement.

What is Abstract in Java?

In simple terms, abstract in Java means hiding complexity and uncovering only the essential parts of an object or system. It provides a way to design programs that separate the high-level functionality from intricate implementation details. This design approach makes your programs easier to understand and maintain.

For example: you are using a car. You only need to know how to use the steering wheel, pedals, and gear lever to drive it. You don’t need to worry about how the engine or braking system works. Java’s abstraction works in the same way: it provides a clear interface or outline to interact with objects without revealing the internal processes.

What is the Interface and Abstract class in Java?

There are two ways provided by Java programming language for data abstraction:

  • Abstract Classes
  • Interfaces
custom img

What is an Abstract Class in Java?

An abstract class is a class that acts as a blueprint for other classes. You cannot create objects directly from an abstract class, but you can use it to provide shared functionality and implement certain behaviours for its subclasses. Abstract classes are declared using the abstract keyword.  

Example Of Abstract Class in Java:

In Java, an abstract class Transportation can represent common vehicle behaviors with abstract methods like move() and fuelEfficiency(). Subclasses such as Car, Bike, and Bus extend this class, each implementing these methods differently while hiding implementation details and maintaining a suitable interface.

custom img

Syntax of Abstract Classes

// Abstract class
abstract class Vehicle {
    abstract void start(); // Abstract method (no body)

    void fuel() { // Non-abstract method (has body)
        System.out.println("Filling fuel.");
    }
}

// Subclass
class Car extends Vehicle {
    void start() { // Implementing abstract method
        System.out.println("Car is starting.");
    }
}

// Main class
public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.start();
        myCar.fuel();
    }
}

Rules of Abstract Classes:

custom img

Features of Abstract Classes:

  • The abstract method does not have a body.
  • Can Contain Abstract and Concrete Methods: Abstract classes can define methods with or without an implementation.
  • Supports Constructors: Unlike interfaces, abstract classes can have constructors, which are used during the creation of subclass instances.

 Code Example:

abstract class Animal {
    String name;

    Animal(String name) { // Constructor
        this.name = name;
    }

    abstract void sound(); // Abstract method

    void display() { // Non-abstract method
        System.out.println("Name: " + name);
    }
}

class Dog extends Animal {
    Dog(String name) { super(name); }

    void sound() { System.out.println("Barks"); }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.display();
        dog.sound();
    }
}

Output:

Name: Buddy
Barks

Complexity:

Space Complexity:O(1)

Time Complexity:O(1)

  • Facilitates Inheritance: Abstract classes serve as a base for other classes, and their abstract methods must be executed by subclasses.

Example of an Abstract Class:

abstract class Animal {
    // Abstract method (no implementation)
    public abstract void makeSound();

    // Concrete method (has implementation)
    public void sleep() {
        System.out.println("The animal is sleeping.");
    }
}

Output

spoj: The program compiled successfully, but main class was not found.
      Main class should contain method: public static void main (String[] args).

To access the abstract class, it must be inherited from another class. Let's convert the Animal class to an abstract class and inherit from it using Dog class

abstract class Animal {
    // Abstract method (no implementation)
    public abstract void makeSound();

    // Concrete method (has implementation)
    public void sleep() {
        System.out.println("The animal is sleeping.");
    }
}

class Dog extends Animal {
    @override
    public void makeSound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound(); // Output: Bark
        myDog.sleep();     // Output: The animal is sleeping.
    }
}

Explanation of the code:

The Animal abstract class acts as a blueprint with two methods. It has an abstract method makeSound, which has no implementation and must be defined by subclasses, 

And a Definite method sleep, which prints "The animal is sleeping.". Since Animal is abstract, you cannot create objects directly from it.

The Dog class extends Animal, inheriting its behavior while providing a detailed implementation for makeSound. The makeSound method in Dog prints "Bark", while the sleep method remains the same as in the Animal class.

In the Main class, an object of Dog is created and referenced by the Animal type. When makeSound is called on this object, it executes the overridden version in Dog, printing "Bark." Calling sleep invokes the inherited implementation from the Animal class, printing "The animal is sleeping."

Output:

Bark 
The animal is sleeping.

2. What is Abstract Method in Java?

An abstract method is a method declared in an abstract class without providing its implementation. Subclasses must override abstract methods to provide specific functionality.

Syntax of Abstract Methods

// Abstract class with an abstract method
abstract class Example {
    abstract void display(); // Method without a body
}

// Subclass providing the method's body
class Demo extends Example {
    void display() {
        System.out.println("Abstract method is now implemented.");
    }
}

Characteristics of Abstract Methods:

  • No Body: Abstract methods only define the method signature but have No Body.
  • Must Be Implemented: Subclasses are required to provide implementations for all inherited abstract methods.
  • Declared Inside Abstract Classes: You can only define abstract methods in abstract classes.
  • You need to use the concrete classes to contain the program logic.

What is Abstraction in Java with example?:

abstract class Shape {
    // Abstract method
    public abstract double calculateArea();
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

public class Main {
    public static void main(String[] args) {
        Shape myCircle = new Circle(5);
        System.out.println("Area: " + myCircle.calculateArea()); // Output: Area: 78.53981633974483
    }
}

Explanation of the code:

The Shape class is an abstract class that represents the structure for its subclasses by including an abstract method calculateArea. This method has no implementation and must be overridden by any class that expands shape.

The Circle class extends Shape and provides a definite implementation for the calculateArea method. It has a private field radius to store the radius of the circle. The constructor of Circle initializes the radius, and the calculateArea method calculates the area of the circle using the formula π×radius(radius) returning the result.

In the Main class, a Circle object is made with a radius of 5, and it is assigned to a variable of type Shape. When the calculateArea method is called on the myCircle object, the overridden method in the Circle class executes which calculates and returns the area of the circle.

Output:

Area: 78.53981633974483

When to Use Abstract Classes and Abstract Methods?

Abstract classes and methods are essential concepts in object-oriented programming that improve code organization and design. An abstract class acts as a blueprint that allows shared attributes and methods while defining abstract methods for subclasses to implement. 

Consider a classic “vehicle” example, perhaps used in a transportation management system or simulation game. The base type is “vehicle,” and each vehicle has a type, purpose, and so on. From this, specific types of vehicles are derived (inherited) — car, bicycle, truck, and so on — each of which has additional characteristics and behaviors. 

For example, some vehicles may have different fuel efficiencies, and some have unique features such as the number of doors or gears. Certain behaviors, like how the vehicle moves or operates, may differ as well. The type hierarchy explains both the similarities and differences between the vehicles.

custom img

Code:

// Abstract class Vehicle
abstract class Vehicle {
    protected String type;

    // Constructor to initialize type
    public Vehicle(String type) {
        this.type = type;
    }

    // Abstract methods
    public abstract String move();
    public abstract double fuelEfficiency();

    // Concrete method
    public String getType() {
        return type;
    }
}

// Concrete class Car
class Car extends Vehicle {
    private int numDoors;

    // Constructor to initialize type and number of doors
    public Car(String type, int numDoors) {
        super(type);
        this.numDoors = numDoors;
    }

    // Implement abstract methods
    @Override
    public String move() {
        return "The car drives on roads.";
    }

    @Override
    public double fuelEfficiency() {
        return 15.5; // Example value (miles per gallon or km/l)
    }

    // Additional method for Car
    public int getNumDoors() {
        return numDoors;
    }
}

// Concrete class Bicycle
class Bicycle extends Vehicle {
    private int gearCount;

    // Constructor to initialize type and gear count
    public Bicycle(String type, int gearCount) {
        super(type);
        this.gearCount = gearCount;
    }

    // Implement abstract methods
    @Override
    public String move() {
        return "The bicycle is pedaled manually.";
    }

    @Override
    public double fuelEfficiency() {
        return Double.POSITIVE_INFINITY; // No fuel needed for bicycles
    }

    // Additional method for Bicycle
    public int getGearCount() {
        return gearCount;
    }
}

// Main class to test abstraction
public class Main {
    public static void main(String[] args) {
        // Create a Car object
        Vehicle car = new Car("Car", 4);
        System.out.println("Type: " + car.getType());
        System.out.println("Movement: " + car.move());
        System.out.println("Fuel Efficiency: " + car.fuelEfficiency() + " km/l");

        // Create a Bicycle object
        Vehicle bicycle = new Bicycle("Bicycle", 21);
        System.out.println("\nType: " + bicycle.getType());
        System.out.println("Movement: " + bicycle.move());
        System.out.println("Fuel Efficiency: " + bicycle.fuelEfficiency());
    }
}

Output:

Type: Car
Movement: The car drives on roads.
Fuel Efficiency: 15.5 km/l

Type: Bicycle
Movement: The bicycle is pedaled manually.
Fuel Efficiency: Infinity

Explanation Of Code:

This program explains abstraction in Java using the "Vehicle" hierarchy. The abstract class Vehicle defines shared properties and behaviors for all vehicles, such as the type and the abstract methods move() and fuelEfficiency(). The concrete subclasses, Car and Bicycle, inherit from Vehicle and implement the abstract methods according to their specific behaviors. 

For example, a Car moves on roads and has a fuel efficiency of 15.5 km/l, while a Bicycle is manually pedaled and doesn't consume fuel. The main method shows polymorphism by using the Vehicle reference to call methods for both Car and Bicycle objects.

The design effectively separates shared attributes (e.g., type) and unique characteristics (e.g., numDoors for cars and gearCount for bicycles), showing the benefits of abstraction. The move() and fuelEfficiency() methods are implemented differently for each subclass to represent their unique behaviors, encapsulating the idea of real-world objects in a programming context. 

Time and Space Complexity:

  • Time Complexity: The program operates with a constant time complexity of O(1) for each method call since there are no loops or recursive calls involved.
  • Space Complexity: The space complexity is O(1) for each object, as only primitive attributes (like type, numDoors, gearCount) are stored. Additional memory is used for object creation but this scales linearly with the number of objects.

Interfaces in Java

An interface in Java is probably the most powerful tool for achieving abstraction. It acts like a contract that defines a set of methods a class must implement. Unlike abstract classes, the key difference is that, by using interfaces, we can achieve 100% abstraction in Java classes. interfaces allow multiple inheritances, which means a class can implement several interfaces.

Features of Interfaces:

  • Interface fields by default are public, static, and final.
  • Interface methods are public and abstract by default. 
  • Interfaces include both methods and variables but lack a method body.
  • Cannot Contain Concrete Methods (Before Java 8): Methods in interfaces were fully abstract until Java 8. From Java 8 onwards, interfaces can include default and static methods with implementations.
  • No Constructors: Interfaces do not have constructors and cannot create objects directly.
  • Implicitly Public Methods: All methods in an interface are implicitly public and abstract.
  • Supports Multiple Inheritance: A class can implement multiple interfaces.
  • Apart from abstraction, interfaces can also be used to implement inheritance in Java.

Syntax of Interface:

// Declaring an interface
interface Shape {
    void draw(); // Automatically public and abstract
}

// Class implementing the interface
class Circle implements Shape {
    public void draw() { // Implementation of the interface method
        System.out.println("Drawing a circle.");
    }
}

// Testing the implementation
public class Main {
    public static void main(String[] args) {
        Shape shape = new Circle(); // Polymorphic reference
        shape.draw();
    }
}

Example of an Interface:

interface Vehicle {
    void start(); // Abstract method
    void stop();  // Abstract method
}

class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("Car is starting...");
    }

    @Override
    public void stop() {
        System.out.println("Car is stopping...");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Output: Car is starting...
        myCar.stop();  // Output: Car is stopping...
    }
}

Explanation of the code:

An interface in Java is like a contract. It says, "If you want to create a class that follows this contract, you must have these methods." The Vehicle interface has two methods which are start() and stop() but it doesn’t say how they work.

The Car class follows the contract of the Vehicle interface. It tells us, "When I start, I will print 'Car is starting...' and when I stop, I will print 'Car is stopping...'".

In the Main class, we create a Car object, but we treat it like a Vehicle. When we call start() or stop(), the Car version of those methods runs.

Output:

Car is starting... 
Car is stopping...

Important Properties of Abstraction in Java

Abstraction in Java is an important concept in object-oriented programming that hides the complex details of how something works, this shows only the essential features to the user.

Here are some properties of abstraction in Java that you should know.

Encapsulation:

Encapsulation combines data and methods in a single unit (class). It contains external access to certain details, which protects the data from accidental changes. Developers can modify the internal workings of a class without affecting the code that uses it, improving security and making the system easier to maintain.

Modularity:

Abstraction breaks a system into smaller, separate parts, which makes it easier to develop, test, and fix code. It also allows teams to work on different parts at the same time without causing conflicts.

Polymorphism:

Polymorphism allows objects to be treated as their parent class and enables the same method to behave differently based on the object calling it. 

Extensibility:

Abstraction allows adding new functionality without altering the system’s core structure. Developers can create base classes or interfaces as a foundation for future extensions.

Information Hiding:

This principle hides extreme details of an object which exposes only the essential parts. This improves security and reduces complexity making the system easier for users and developers to handle.

Code Reusability:

Abstraction supports creating generalized solutions that can be reused in multiple parts of a program or different projects. Abstract classes and interfaces define shared behaviors which reduces duplication and saves development time.

Types Of Abstraction In Java

Here are the types of abstraction in Java that are important to understand. They help simplify complex systems by focusing on essential details.

Data Abstraction:

Focuses on hiding the internal details of how data is stored or represented. Developers interact with data through interfaces or abstract methods, without needing to know the details of its implementation.

Control Abstraction:

It hides the details of how operations are performed. It provides simplified interfaces for complex processes, so developers and users don’t need to understand the full workings of those operations.

Difference between Abstraction and Encapsulation?

Although abstraction and encapsulation are related concepts in OOP, they differ significantly:

Feature Abstraction Encapsulation
Usage Usage Abstraction is the outer layout that is used in terms of design. Encapsulation is the inner layout used in terms of implementation.
Focus or Purpose It hides implementation details while showing functionality. It hides data, code and controls access.
Achieved By This can abstract classes and interfaces. This can access modifiers (private, protected, public)
Purpose It simplifies usage and improves readability. It protects data and maintains integrity.
Example Using abstract methods for behaviors. Using getters and setters to control access.

Real-World Analogy of Abstraction

Let’s consider the example of an ATM machine. Users interact with an ATM by pressing buttons to withdraw cash, check balances, or transfer money. The complex operations behind these actions (e.g., account verification, and database transactions) remain hidden. In Java, abstraction works similarly to provide a clear interface for users while concealing the intricate backend details.

Example Code:

abstract class ATM {
    public abstract void withdraw(int amount);

    public void showMessage() {
        System.out.println("Please follow the instructions on the screen.");
    }
}

class BankATM extends ATM {
    @Override
    public void withdraw(int amount) {
        System.out.println("Dispensing " + amount + " dollars.");
    }
}

public class Main {
    public static void main(String[] args) {
        ATM myATM = new BankATM();
        myATM.showMessage(); // Output: Please follow the instructions on the screen.
        myATM.withdraw(100); // Output: Dispensing 100 dollars.
    }
}

Explanation of the code:

The ATM abstract class sets up a basic structure for ATM functionality. It has one method, withdraw(), that subclasses must define, and another, showMessage(), which provides a standard message: "Please follow the instructions on the screen."

The BankATM class extends ATM and defines the withdraw() method. It prints a message like "Dispensing [amount] dollars," while the showMessage() method is inherited from the ATM class without changes.

Output:

Please follow the instructions on the screen. 
Dispensing 100 dollars.

How does Abstraction Contribute to Scalability in Java?

Abstraction facilitates complex systems by splitting them into smaller, manageable parts. This makes it easier to work on individual pieces and ensures the entire system is easier to understand, maintain, and scale as needed.

One major advantage is easier maintenance. Since abstraction separates what a system does from how it works, developers can make changes to specific parts without affecting the rest of the system. 

Adding new features is also straightforward with abstraction. You can introduce new functionality without changing the existing code which follows the principle of extending systems without modifying their core parts. This keeps the system stable and reduces the risk of errors.

Abstraction also supports teamwork. Different teams can work on separate parts of the system at the same time, as long as they follow shared rules or interfaces. This speeds up development and prevents conflicts during integration.

By reducing the connections between components, abstraction assures that changes in one part don’t disrupt others. It also allows developers to optimize specific parts for better performance without needing to modify the whole system.

Advantages Of Abstraction In Java

Here are some advantages of Abstraction in Java that you should know:

  1. Simplifies Complexity: Abstracting complex logic improves program readability and usability.
  2. Enhances Reusability: Abstract classes and interfaces promote code reuse by defining shared behavior.
  3. Improves Maintainability: Clear separation between interfaces and implementations makes maintaining code easier.
  4. Promotes Security: Abstraction can help hide sensitive details from external users.
  5. Supports Scalability: Well-abstracted systems are easier to extend with new features.

Disadvantages Of Abstraction In Java

  1. Performance Overhead: Abstraction adds extra layers that can increase memory use and slow execution, which harms performance in resource-heavy applications.
  2. Mapping Challenges: Bridging object-oriented programming with relational databases can complicate data retrieval and mapping.
  3. Complex Code: Overusing abstraction with too many abstract classes and interfaces can create confusing code which makes it more difficult for new developers to understand and maintain.
  4. Limited Low-Level Access: Java’s focus on abstraction limits low-level programming, which is necessary for tasks like hardware interaction or performance optimization.

Conclusion

Abstraction is an essential concept in Java and object-oriented programming. It simplifies development by focusing on essential features while hiding complex details. Using abstract classes and interfaces, Java allows developers to create flexible, maintainable, and scalable applications.

By applying abstraction, programmers can design modular code that's easy to extend, debug, and reuse which results in efficient and user-friendly systems.

Frequently Asked Questions

What is Java Abstraction?

Java abstraction streamlines programming by concentrating only on the important details of an object while hiding the complex implementation. It is achieved using abstract classes and interfaces.

What is an Abstract Class in Java?

An abstract class is a type of class that cannot be directly used to create objects. It can include abstract methods and regular methods. Subclasses use it as a foundation to build on.

What is an Abstract Method in Java?

An abstract method is defined without a body which means it has no code. This method must be implemented in any class that extends the abstract class or implements the interface containing it.

How is Abstraction Achieved in Java?

Java supports abstraction through abstract classes and interfaces. Abstract classes have a partial implementation, while interfaces define the behavior that classes must follow without implementation.

What is the Difference Between an Abstract Class and an Interface?

Abstract classes can include abstract and non-abstract methods, and have constructors. Interfaces, however, especially define abstract methods. Since Java 8, interfaces can also have default and static methods, but they cannot store state.

Why is Abstraction Used in Java?

Abstraction makes code simpler by reducing complexity and helps in building reusable, modular, and secure applications. It also protects sensitive details by exposing only what is necessary to the user.

Can Abstract Classes Have Constructors?

Yes, abstract classes can have constructors. These constructors are called during the creation of objects of subclasses, even though the abstract class itself cannot be instantiated.

Is it Possible to Create Objects of an Abstract Class?

No, you cannot directly create objects of an abstract class. Yet, you can create objects of subclasses that implement the abstract methods which allows them to fully utilize the abstract class's functionality.

Read More Articles

Chat with us
Chat with us
Talk to career expert