Home ยป Aggregation in Java Tutorial with Code Examples

Aggregation in Java Tutorial with Code Examples

Aggregation is a key concept in object-oriented programming (OOP) that represents a “has-a” relationship between two classes. In Java, aggregation allows one class to be a part of another class, but both classes maintain their independence.

Unlike inheritance, where one class extends another, aggregation focuses on how classes are related by ownership.

This tutorial will guide you through understanding aggregation in Java, how to implement it, and its practical use cases with examples.

Table of Contents:

1. What is Aggregation?

Aggregation is a type of association where one class contains a reference to another class. It represents a whole-part relationship, where the “whole” can exist independently of the “part.” In aggregation, one class acts as a container (or aggregator) and contains objects of another class.

For example:

A Library contains multiple Books.
A Car has Engine, Tires, and Seats.

In these cases, if the Library object is destroyed, the Books objects can still exist independently, which is what distinguishes aggregation from composition.

Key Characteristics of Aggregation:

Represents a “has-a” relationship.
The lifetime of the contained objects (parts) is independent of the container object (whole).
Both objects are related but can exist independently.

2. Difference Between Aggregation and Composition

Aggregation:

The child (part) can exist independently of the parent (whole).
Example: A Student has an Address, but an Address can exist without a Student.

Composition:

The child (part) cannot exist independently of the parent (whole).
Example: A Car has an Engine, and if the Car is destroyed, the Engine is also destroyed.

Key Difference:

In composition, the lifetime of the part depends on the whole.
In aggregation, the lifetime of the part is independent of the whole.

3. Implementing Aggregation in Java

In Java, aggregation is implemented by defining a class that holds a reference to another class as a field.

The referenced object (part) can be passed through the constructor, setter, or directly instantiated.

4. Code Example of Aggregation

Example 1: Aggregation between Student and Address

// Part class (Address)
class Address {
    String city;
    String state;
    String country;

    // Constructor
    public Address(String city, String state, String country) {
        this.city = city;
        this.state = state;
        this.country = country;
    }

    public void displayAddress() {
        System.out.println("City: " + city);
        System.out.println("State: " + state);
        System.out.println("Country: " + country);
    }
}

// Whole class (Student)
class Student {
    String name;
    int rollNo;
    Address address;  // Aggregation (Address is part of Student)

    // Constructor
    public Student(String name, int rollNo, Address address) {
        this.name = name;
        this.rollNo = rollNo;
        this.address = address;  // Aggregation
    }

    public void displayInfo() {
        System.out.println("Student Name: " + name);
        System.out.println("Roll No: " + rollNo);
        address.displayAddress();  // Calling the address object
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an Address object (can exist independently of Student)
        Address address = new Address("New York", "NY", "USA");

        // Creating a Student object that aggregates Address
        Student student = new Student("John", 101, address);

        // Displaying Student and Address information
        student.displayInfo();
    }
}

Output:

Student Name: John
Roll No: 101
City: New York
State: NY
Country: USA

Explanation:

Student has an Address, but both classes can exist independently.
The Address object is passed to the Student constructor, illustrating aggregation where Address can exist without Student.

5. Aggregation vs Inheritance

Aggregation:

Represents a “has-a” relationship (e.g., a Car has-a Engine).
Promotes code reuse by including existing objects within other objects.
The child object can exist independently of the parent.

Inheritance:

Represents an “is-a” relationship (e.g., a Dog is-a Animal).
Allows a class to inherit the behavior and properties of another class.
The child class is dependent on the parent class in terms of behavior.

Example 2: Aggregation vs Inheritance

// Inheritance (Animal and Dog)
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound.");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks.");
    }
}

// Aggregation (Car and Engine)
class Engine {
    public void start() {
        System.out.println("Engine is starting.");
    }
}

class Car {
    Engine engine;  // Aggregation

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void startCar() {
        engine.start();  // Car uses Engine
        System.out.println("Car is ready to drive.");
    }
}

public class Main {
    public static void main(String[] args) {
        // Inheritance Example
        Dog dog = new Dog();
        dog.sound();  // Output: Dog barks.

        // Aggregation Example
        Engine engine = new Engine();
        Car car = new Car(engine);
        car.startCar();  // Output: Engine is starting. Car is ready to drive.
    }
}

Explanation:

The Dog class inherits the behavior of Animal using the “is-a” relationship.
The Car class uses Engine in an aggregation relationship, as “has-a”, where Car depends on Engine but Engine can exist independently.

6. Advantages of Aggregation

Code Reusability: Aggregation allows you to reuse existing objects in new contexts, reducing code duplication.
Flexibility: Since the child (part) object can exist independently, aggregation allows greater flexibility and modular design.
Loose Coupling: Aggregation reduces coupling between classes. The “whole” class can function without being tightly bound to the “part” class.

7. Real-World Use Cases of Aggregation

1. Library and Books:

A Library contains multiple Books, but the Books can exist independently of the Library.

Example 3: Library and Book Aggregation

import java.util.List;
import java.util.ArrayList;

// Part class (Book)
class Book {
    String title;
    String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    public void displayBookInfo() {
        System.out.println("Title: " + title + ", Author: " + author);
    }
}

// Whole class (Library)
class Library {
    String name;
    List books;  // Aggregation

    public Library(String name) {
        this.name = name;
        this.books = new ArrayList<>();
    }

    public void addBook(Book book) {
        books.add(book);  // Aggregating books in the library
    }

    public void displayLibraryInfo() {
        System.out.println("Library: " + name);
        System.out.println("Books in library:");
        for (Book book : books) {
            book.displayBookInfo();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating books
        Book book1 = new Book("Effective Java", "Joshua Bloch");
        Book book2 = new Book("Clean Code", "Robert C. Martin");

        // Creating a library and adding books
        Library library = new Library("City Library");
        library.addBook(book1);
        library.addBook(book2);

        // Displaying library information
        library.displayLibraryInfo();
    }
}

Output:

Library: City Library
Books in library:
Title: Effective Java, Author: Joshua Bloch
Title: Clean Code, Author: Robert C. Martin

Explanation:

Library aggregates Book objects. The books can exist independently, but they are associated with the library in this example.

2. Department and Employees:

A Department has multiple Employees, but Employees can exist without the Department.

8. Conclusion

Aggregation in Java allows classes to have a “has-a” relationship, promoting code reusability and flexibility.

Unlike composition, the lifetime of the part (contained object) is independent of the whole (container object), making aggregation a looser form of association.

By using aggregation, you can structure your code to model real-world relationships effectively.

Understanding the difference between aggregation and inheritance, as well as when to use each, is essential for writing clean, maintainable, and modular Java programs.

You may also like