11
OctWhat is Abstraction in Java with Examples & Its Uses
Abstraction in Java
Abstraction is a fundamental concept in Java's object-oriented programming. It enables you to hide complex implementation details and display only the most essential features of an object. This provides a more explicit and simpler interface to the outside world, making the system easier to understand and manage.
In this Java Tutorial, we will discuss Abstraction in Java with proper illustrations. We will explain abstract classes, abstract methods, and interfaces, the difference between abstract classes and interfaces, and the pros and cons of abstraction with examples. So, let's start by discussing "What is Abstraction?"
Fast-track your tech career with our Java Full Stack Developer Course —start learning today!
Before moving further, you need to be thorough with the following concepts; otherwise, you won't understand this topic completely: |
Read More: Top 50 Java Interview Questions For Freshers |
What is Abstraction in Java?
- Abstraction in Java is the technique of hiding implementation details and displaying only functionality to the user.
- It reduces complexity and allows the programmer to concentrate on the object's functionality rather than its implementation.
- It enables developers to create complex applications without having to worry about low-level details such as Java data types and variables, memory management, and platform independence.
Abstraction in Java is performed in two ways:
- Abstract Classes
- Interfaces
1. Abstract Class in Java
- An abstract class is a class that has been declared abstract. It might include both abstract and non-abstract approaches.
- It needs to be expanded and its method implemented.
- It cannot be instantiated. It can have both constructors and static methods.
- Final methods can prevent subclasses from changing their methods' contents.
Rules for Java Abstract Class
- An abstract class must be declared with the abstract keyword.
- It can have abstract and non-abstract methods.
- It cannot be instantiated.
- It can have final methods.
- It can also have constructors and static methods.
Abstract Method in Java
- In Java, an abstract method is declared but not implemented. It is specified within an abstract class and must be overridden by its subclasses.
- An abstract method is intended to be a placeholder that enforces specific behavior in subclasses.
- It serves a useful purpose when the desired behavior of the method should remain consistent while allowing different implementations within different classes.
Read More: Java Developer Salary In India |
When should abstract classes and abstract methods be used?
- Use abstract classes to create a template for subclasses with similar features and behaviors.
- Declare abstract methods to outline the functionality that subclasses must implement.
- Use abstract classes to provide limited implementations (default behavior) for specific methods.
- Unlike interfaces, abstract classes provide more control over member access (protected fields).
- Use abstract classes when creating a class hierarchy with closely related subclasses.
Algorithm to Implement Abstraction in Java
- Identify the classes or interfaces that will form the abstraction.
- Create an abstract class or interface to describe common behaviors and properties among these classes.
- Define abstract methods in the abstract class or interface that do not require implementation details.
- Use concrete classes to extend abstract classes or implement interfaces.
- Override abstract methods in concrete classes for specific implementation.
- Use concrete classes to implement program logic.
Example of Java Abstraction Using Abstract Classes and Abstract Methods
// Define the abstract class
abstract class Animal {
// Abstract method (does not have a body)
public abstract void makeSound();
// Regular method
public void sleep() {
System.out.println("Zzz...");
}
}
// Subclass (inherited from Animal)
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof");
}
}
// Subclass (inherited from Animal)
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
// Use the abstract class
class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound(); // Output: Woof
dog.sleep(); // Output: Zzz...
cat.makeSound(); // Output: Meow
cat.sleep(); // Output: Zzz...
}
}
In this example, Animal is an abstract class with one abstract method, makeSound, and one regular method, sleep. Dog & Cat are subclasses that extend Animal and implement the makeSound function. In the Main class, Dog and Cat instances are created, and their respective methods are called. Animals cannot be instantiated directly; however, their subclasses can be utilized to generate objects.
Output
Woof
Zzz...
Meow
Zzz...
2. Interface in Java
- Interfaces are another way of implementing abstraction in Java. The fundamental distinction is that using interfaces allows us to achieve 100% abstraction in Java classes.
- Interfaces, whether in Java or another language, contain both methods and variables but lack a method body. In addition to abstraction,
Interfaces can be used to implement interfaces in Java.
- As with the abstract class, it cannot be instantiated.
- Since Java 8, we can include default and static methods in interfaces.
- Since Java 9, we can include private methods in interfaces.
Syntax of Interface Declaration
The interface keyword is used to declare a new interface. It provides an entire abstraction, which implies that all methods in an interface are defined with an empty body, and all fields are public, static, and final by definition. A class that implements an interface must include all of the methods specified in the interface.
interface {
// declare constant fields
// declare methods that abstract
// by default.
}
Why do classes implement interfaces?
- It is used to accomplish complete abstraction. Because Java does not permit multiple inheritances for classes, utilizing an interface allows for multiple inheritances.
- Any class can only extend one class, but it can implement an endless number of interfaces. It is also used to create loose coupling.
Read More: Multiple Inheritance in Java |
Which classes should implement the interface?
- If a class includes basic business logic and is the only implementation of an interface, build a concrete class instead.
- Implement details like persistence, REST calls, and UI on an "external" layer using an interface.
Example of Java Interface
public class Main {
// Define the Vehicle interface
public interface Vehicle {
// Abstract method to start the vehicle
void start();
// Abstract method to stop the vehicle
void stop();
}
// Implement the Vehicle interface in the Car class
public static class Car implements Vehicle {
@Override
public void start() {
System.out.println("The car is starting.");
}
@Override
public void stop() {
System.out.println("The car is stopping.");
}
}
public static void main(String[] args) {
// Create an instance of Car
Vehicle myCar = new Car();
// Call methods defined in the interface
myCar.start(); // Output: The car is starting.
myCar.stop(); // Output: The car is stopping.
}
}
The Vehicle interface provides two methods: start() and stop(), which every implementing class must implement. The Car class implements these methods in specific ways. The main() method creates a car object as a vehicle and calls it the start() and stop() methods.
Output
The car is starting.
The car is stopping.
Java 8 Default Method in Interface
Since Java 8, we can include method bodies in interfaces. But we need to make it the default method.
Example of Default Method in Java Interface
class Main {
// Define the Shape interface
public interface Shape {
// Abstract methods to be implemented by any class that implements this interface
double getArea();
double getPerimeter();
// Default method to describe the shape
default void describe() {
System.out.println("This is a shape.");
}
}
// Implement the Shape interface in the Square class
public static class Square implements Shape {
private double side;
public Square(double side) {
this.side = side;
}
@Override
public double getArea() {
return side * side;
}
@Override
public double getPerimeter() {
return 4 * side;
}
}
// Implement the Shape interface in the Triangle class
public static class Triangle implements Shape {
private double a, b, c; // sides of the triangle
public Triangle(double a, double b, double c) {
this.a = a;
this.b = b;
this.c = c;
}
@Override
public double getArea() {
double s = (a + b + c) / 2;
return Math.sqrt(s * (s - a) * (s - b) * (s - c));
}
@Override
public double getPerimeter() {
return a + b + c;
}
}
public static void main(String[] args) {
// Create instances of Square and Triangle
Shape mySquare = new Square(4.0);
Shape myTriangle = new Triangle(3.0, 4.0, 5.0);
// Call the abstract methods defined in the interface
System.out.println("Square Area: " + mySquare.getArea()); // Output: Square Area: 16.0
System.out.println("Square Perimeter: " + mySquare.getPerimeter()); // Output: Square Perimeter: 16.0
mySquare.describe(); // Output: This is a shape.
System.out.println("Triangle Area: " + myTriangle.getArea()); // Output: Triangle Area: 6.0
System.out.println("Triangle Perimeter: " + myTriangle.getPerimeter()); // Output: Triangle Perimeter: 12.0
myTriangle.describe(); // Output: This is a shape.
}
}
This Java code creates an interface Shape with getArea(), getPerimeter(), and a default describe() function. It then uses this interface in the Square and Triangle classes to determine the area and perimeter. In main(), instances of Square and Triangle are created, their functions are invoked to compute geometric characteristics, and the describe() method returns a generic shape description for each.
Output
Square Area: 16.0
Square Perimeter: 16.0
This is a shape.
Triangle Area: 6.0
Triangle Perimeter: 12.0
This is a shape.
Java 8 Static Method in Interface
Since Java 8, we can include static methods in interfaces.
Example of Static Method in Java Interface
class Main {
// Define the Operation interface
public interface Operation {
// Abstract method to perform an operation
double execute(double a, double b);
// Static method to provide a default calculation for addition
static double add(double a, double b) {
return a + b;
}
}
// Implement the Operation interface in the Addition class
public static class Addition implements Operation {
@Override
public double execute(double a, double b) {
return a + b;
}
}
// Implement the Operation interface in the Multiplication class
public static class Multiplication implements Operation {
@Override
public double execute(double a, double b) {
return a * b;
}
}
public static void main(String[] args) {
// Create instances of Addition and Multiplication
Operation addition = new Addition();
Operation multiplication = new Multiplication();
// Call the execute method defined in the interface
System.out.println("Addition Result: " + addition.execute(5, 3)); // Output: Addition Result: 8.0
System.out.println("Multiplication Result: " + multiplication.execute(5, 3)); // Output: Multiplication Result: 15.0
// Call the static method from the Operation interface
System.out.println("Static Addition Result: " + Operation.add(7, 2)); // Output: Static Addition Result: 9.0
}
}
This Java code creates an Operation interface that includes an execute() method for operations and a static add() addition method. The Addition class uses the Operation interface to conduct addition, whereas the Multiplication class uses it to accomplish multiplication.
The main() method creates instances of Addition and Multiplication and calls their execute() methods to demonstrate their respective operations. The static add() method is directly from the Operation interface.
Output
Addition Result: 8.0
Multiplication Result: 15.0
Static Addition Result: 9.0
Why do we use an Interface in Java?
Here are some reasons why we use an interface in Java:
- To achieve abstraction: Interfaces can be used to achieve abstraction, which is an essential aspect of object-oriented programming. By defining an interface, anyone can separate the implementation of a class from its behavior.
- To provide multiple inheritances: Java doesn't support multiple inheritances of classes, but the developer can achieve a similar effect by using interfaces. A class can implement multiple interfaces, which allows it to inherit the behavior of all the interfaces it implements.
- To define constants: Interfaces can be used to define constants that are shared by multiple classes.
- To define callbacks: Interfaces can be used to define callbacks, which are methods that are called by an object in response to an event.
- To achieve polymorphism: Interfaces can be used to achieve polymorphism, which is the ability of objects of different classes to be used interchangeably. By defining a standard interface, the programmer can write code that works with any object that implements that interface.
Abstract Class Vs. Interface in Java
Feature | Abstract Class | Interface |
Method Types | It can have abstract and non-abstract methods. | It can only have abstract methods (except for Java 8's default and static methods) |
Multiple Inheritance | Not supported | Supported |
Variable Types | It can have final, non-final, static, and non-static variables. | It can only have static and final variables (implicitly) |
Implementation | Can provide an implementation for interfaces | Cannot provide an implementation for abstract classes |
Declaration Keyword | abstract | interface |
Inheritance | Can extend one class and implement multiple interfaces | Can only extend other interfaces |
Extending/Implementing Keyword | Extends for class inheritance, implements for interface implementation | Implements for interface implementation |
Member Access Modifiers | Can have private, protected, and public members | Members are public by default |
Example | public abstract class Shape { public abstract void draw(); } | public interface Drawable { void draw(); } |
Example Illustrating Abstract Class and Interface in a Java Program
Let's look at a basic example that uses both an interface and an abstract class.
class Main {
// Define the Shape interface
public interface Shape {
double getArea();
double getPerimeter();
}
// Define an abstract class that implements the Shape interface
public static abstract class AbstractShape implements Shape {
private String color;
public AbstractShape(String color) {
this.color = color;
}
public String getColor() {
return color;
}
public void showColor() {
System.out.println("Color: " + color);
}
public abstract void draw();
}
// Circle class implementing Shape and extending AbstractShape
public static class Circle extends AbstractShape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
@Override
public void draw() {
System.out.println("Drawing a circle.");
}
}
// Rectangle class implementing Shape and extending AbstractShape
public static class Rectangle extends AbstractShape {
private double width, height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
@Override
public double getPerimeter() {
return 2 * (width + height);
}
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}
public static void main(String[] args) {
Shape circle = new Circle("red", 5.0);
Shape rectangle = new Rectangle("blue", 4.0, 6.0);
System.out.println("Circle Area: " + circle.getArea());
System.out.println("Circle Perimeter: " + circle.getPerimeter());
((AbstractShape) circle).showColor();
((AbstractShape) circle).draw();
System.out.println("Rectangle Area: " + rectangle.getArea());
System.out.println("Rectangle Perimeter: " + rectangle.getPerimeter());
((AbstractShape) rectangle).showColor();
((AbstractShape) rectangle).draw();
}
}
The Java code includes a Shape interface with methods for area and perimeter calculation. An AbstractShape abstract class implements Shape, includes a color field with showColor(), and declares draw() abstract. Circle and Rectangle expand AbstractShape by defining area, perimeter, and draw methods. In main(), Circle and Rectangle objects demonstrate method calls and interface polymorphism.
Output
Circle Area: 78.53981633974483
Circle Perimeter: 31.41592653589793
Color: red
Drawing a circle.
Rectangle Area: 24.0
Rectangle Perimeter: 20.0
Color: blue
Drawing a rectangle.
Advantages of Abstraction in Java
- It simplifies the way we observe things.
- Reduces code duplication and promotes reusability.
- Improves application or program security by limiting user access to only necessary information.
- It promotes application maintainability.
- Improves the application's modularity.
- We can make changes to our internal system without affecting end-users, making enhancements much more accessible.
- Promotes code reuse and maintainability.
- Minimises implementation details and only provides necessary information.
- Ensures a clear and straightforward user interface.
- Improves security by restricting access to internal class information.
Disadvantages of Abstraction in Java
- Abstraction may prevent understanding of the system's functionality.
- Improper use may result in additional complexity. This may limit implementation flexibility.
- Improper use of abstraction can increase code complexity, resulting in longer development times and effort.
- Unfamiliarity with abstraction layers and implementation specifics might hinder code understanding and debugging.
- Excessive abstraction might lead to slower performance as it adds layers of code and indirections.
Encapsulation vs Data Abstraction
Encapsulation | Data Abstraction |
They combine methods and data into one class and limit access to data members. | By creating classes based on crucial traits and behaviors, complicated systems can be made simpler. |
Control over who has access to private data. | Exposing key functionalities while obscuring implementation details. |
Access modifiers (such as private, protected, and public) are used to do this. | Emphasizes the development of abstract methods and high-level interfaces. |
Giving regulated access helps maintain the security and integrity of data. | Reducing complexity, making it easier to maintain, and offering a straightforward interface. |
Public getter/setter methods and private fields are used to access and change data. | Developing abstract classes or interfaces that have abstract methods that subclasses can implement. |
Also, read the related interview articles like: |
Summary
Java data abstraction improves modularity, encourages code reuse, simplifies complex implementations, and fortifies security by restricting access to essential information. It prioritizes functionality above implementation details, making software systems more straightforward and manageable.
Understanding how to use abstraction through abstract classes or interfaces allows you to create more flexible, scalable programs that are easier to maintain and modify. You can consider enrolling in our Java Full Stack Course to implement what you learned about Abstraction in Java.