Popular Searches
Popular Course Categories
Popular Courses

Working with Composition and Aggregation

Working with Composition and Aggregation

Abstraction, Interfaces, and Object Relationships

Working with Composition and Aggregation in Java

Course: Core Java Training

Topic: Working with Composition and Aggregation

Course URL: Core Java Training Course

Demo URL: Register for a Course Demo

Website: JustAcademy


1. Introduction to Composition and Aggregation

Java is an object-oriented programming language that allows developers to model real-world relationships between objects. In addition to inheritance, Java supports relationships in which one object contains or uses another object. These relationships are commonly described as has-a relationships.

Composition and aggregation are two important forms of relationships between classes. Both allow one class to hold references to objects of another class, but they differ in ownership, independence, and object lifecycle.

For example, a computer contains components such as a motherboard, while a department may have employees who can continue working even if the department is reorganized. These scenarios help explain the difference between strong ownership and a looser relationship.

2. Learning Objectives

  • Understand the meaning of composition and aggregation in Java.
  • Learn how to implement both relationships using classes and object references.
  • Understand the difference between strong and weak ownership.
  • Explore real-world examples and practical Java programs.
  • Compare composition, aggregation, association, and inheritance.
  • Learn when to use each relationship in application design.
  • Identify common programming mistakes and prepare for interview questions.

3. Understanding the Has-A Relationship

A has-a relationship exists when an object contains a reference to, or uses, another object as part of its functionality. Composition and aggregation are both forms of this relationship.

For example, consider a Car class that contains an Engine object. The car uses the engine to perform its operations. A Department class may contain references to several Employee objects.

Basic Example

class Engine {
    void start() {
        System.out.println("Engine started.");
    }
}

class Car {
    private Engine engine;

    Car() {
        engine = new Engine();
    }

    void startCar() {
        engine.start();
        System.out.println("Car is ready.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.startCar();
    }
}

Output:

Engine started.
Car is ready.

The Car class contains an Engine reference and calls its method. This example illustrates a has-a relationship implemented through object composition.

4. What Is Composition in Java?

Composition is a strong whole-part relationship in which one object owns another object as an integral part of its design. The contained object's lifecycle is generally managed by the owning object, and the contained part is not intended to exist independently within that domain model.

Composition is useful when an object is responsible for creating, managing, and using the objects that form its internal structure.

Key Characteristics of Composition

  • Represents a strong whole-part relationship.
  • The owning object controls the contained object's lifecycle by design.
  • The part is generally not shared as an independently owned component.
  • The contained object is commonly created inside the owning class.
  • It improves encapsulation by hiding internal implementation details.
  • It allows a complex object to be built from smaller objects.

Real-World Examples of Composition

  • Order and OrderItem: An order owns its line items in a typical order-management model.
  • House and Room: A house may own room objects as parts of its structure in a particular domain model.
  • Computer and Internal Configuration: A computer object may manage objects representing its internal configuration.
  • Document and Paragraph: A document may own the paragraph objects that make up its content.

These examples are design choices rather than universal rules. The correct relationship depends on whether the part is independently managed or owned by the whole in the application being developed.

5. Implementing Composition in Java

Composition can be implemented by creating an object of one class inside another class. The owning class stores the object in a field and uses it to perform its operations.

Example: Computer and Processor

class Processor {
    void process() {
        System.out.println("Processor is processing data.");
    }
}

class Computer {
    private final Processor processor;

    Computer() {
        processor = new Processor();
    }

    void start() {
        processor.process();
        System.out.println("Computer started.");
    }
}

public class Main {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.start();
    }
}

Output:

Processor is processing data.
Computer started.

Explanation

  1. The Processor class defines a method called process().
  2. The Computer class contains a private reference to a Processor object.
  3. The constructor creates the processor and assigns it to the field.
  4. The start() method uses the processor to perform work.
  5. The main() method creates a computer and starts it.

The final modifier prevents the processor reference from being reassigned after initialization. It does not make the referenced object itself immutable.

6. What Is Aggregation in Java?

Aggregation is a weaker whole-part relationship in which one object holds references to other objects that can exist independently of the containing object.

For example, a department may have employees. If the department is removed or reorganized, the employee objects can continue to exist and may be assigned to another department.

Key Characteristics of Aggregation

  • Represents a relatively weak has-a relationship.
  • The contained objects have independent lifecycles.
  • The containing class typically receives references to existing objects.
  • The same object may be referenced by other parts of the application when the domain allows it.
  • Removing the containing object does not inherently require removing the referenced objects.
  • It supports flexible object relationships and reuse.

Real-World Examples of Aggregation

  • Department and Employee: Employees can exist independently of a particular department.
  • Team and Player: Players can continue to exist and join another team.
  • Library and Book: A book can exist independently of a particular library's collection.
  • Project and Developer: A developer may work on multiple projects over time.

7. Implementing Aggregation in Java

Aggregation is commonly implemented by passing an existing object to another class through a constructor or setter method. The receiving class stores the reference and uses the object without necessarily owning its lifecycle.

Example: Department and Employee

class Employee {
    private final String name;

    Employee(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }
}

class Department {
    private final String departmentName;
    private final Employee employee;

    Department(String departmentName, Employee employee) {
        this.departmentName = departmentName;
        this.employee = employee;
    }

    void displayDetails() {
        System.out.println("Department: " + departmentName);
        System.out.println("Employee: " + employee.getName());
    }
}

public class Main {
    public static void main(String[] args) {
        Employee employee = new Employee("Amit");

        Department department =
            new Department("Information Technology", employee);

        department.displayDetails();

        System.out.println("Employee still exists: "
            + employee.getName());
    }
}

Output:

Department: Information Technology
Employee: Amit
Employee still exists: Amit

Explanation

  1. An Employee object is created independently.
  2. The existing employee object is passed to the Department constructor.
  3. The department stores a reference to that employee.
  4. The department uses the employee object to display details.
  5. The original employee reference remains available independently of the department.

This demonstrates aggregation because the employee is created outside the department and can be used independently. Java does not enforce aggregation as a separate language feature; the relationship is established through the program's design and ownership rules.

8. Composition vs. Aggregation

Feature Composition Aggregation
Relationship Strong whole-part relationship Weak whole-part relationship
Ownership The whole owns the part in the domain model The whole references a part that remains independently managed
Lifecycle Usually managed with the whole Independent of the whole
Object creation Often created within the owning class Often created externally and passed in
Independent existence Part is not intended to exist independently within the modeled relationship Part can exist without the containing object
Sharing Exclusive ownership is generally intended Sharing may be possible
Example Order and its line items Department and employees
Typical implementation Private fields initialized and managed by the owner References supplied through constructors or setters

9. Understanding Object Lifecycle in Java

Java uses garbage collection to reclaim objects that are no longer reachable. It does not automatically destroy an object's referenced parts merely because the containing object is no longer used.

Therefore, the difference between composition and aggregation is primarily a matter of ownership and domain design, rather than a special Java keyword or automatic destruction rule.

Lifecycle in Composition

  • The whole creates or manages the part as part of its own responsibilities.
  • The part is not intended to be managed independently in that domain model.
  • When the whole becomes unreachable, its exclusively owned parts may also become eligible for garbage collection if no other reachable references exist.

Lifecycle in Aggregation

  • The part is created or managed independently.
  • The whole holds a reference to the part but does not necessarily own it.
  • The part can remain reachable and usable after the whole becomes unreachable.

Important: Garbage collection depends on object reachability, not simply on whether a particular reference is called a composition or aggregation relationship.

10. Constructor Injection and Setter Injection

Both composition and aggregation can use constructors or setter methods to connect objects. The choice depends on how the application manages the relationship.

Constructor Injection

Constructor injection supplies a dependency when an object is created. It is useful when the dependency is required for the object to function correctly.

class Printer {
    void print() {
        System.out.println("Printing...");
    }
}

class Office {
    private final Printer printer;

    Office(Printer printer) {
        this.printer = printer;
    }

    void printDocument() {
        printer.print();
    }
}

In this example, an existing Printer is supplied to Office. This can model aggregation when the printer is independently managed.

Setter Injection

Setter injection supplies or changes a dependency after the object has been created. It is useful when a dependency is optional or can be replaced.

class MusicPlayer {
    void play() {
        System.out.println("Music is playing.");
    }
}

class Car {
    private MusicPlayer musicPlayer;

    void setMusicPlayer(MusicPlayer musicPlayer) {
        this.musicPlayer = musicPlayer;
    }

    void playMusic() {
        if (musicPlayer != null) {
            musicPlayer.play();
        } else {
            System.out.println("No music player connected.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.setMusicPlayer(new MusicPlayer());
        car.playMusic();
    }
}

Output:

Music is playing.

The way the object is supplied does not, by itself, determine whether the relationship is composition or aggregation. Ownership and lifecycle semantics determine the intended relationship.

11. Composition, Aggregation, Association, and Inheritance

Association is the general relationship between objects that interact with one another. Aggregation and composition are specialized whole-part forms of association, while inheritance models an is-a relationship.

Concept Meaning Example
Association Objects are related or communicate with each other Doctor and Patient
Aggregation A whole references independently existing parts Team and Player
Composition A whole owns parts as an integrated structure Order and OrderItem
Inheritance One class extends another class to specialize its behavior Car extends Vehicle

Example of Inheritance

class Vehicle {
    void move() {
        System.out.println("Vehicle is moving.");
    }
}

class Car extends Vehicle {
    void openTrunk() {
        System.out.println("Trunk opened.");
    }
}

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.move();
        car.openTrunk();
    }
}

Output:

Vehicle is moving.
Trunk opened.

The car is a vehicle, so inheritance models an is-a relationship. Composition and aggregation instead model has-a relationships.

12. Practical Example: Online Shopping System

An online shopping system can use composition for an order and its line items, while using aggregation to associate an order with a customer who exists independently of that order.

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

class Customer {
    private final String name;

    Customer(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }
}

class OrderItem {
    private final String product;
    private final int quantity;

    OrderItem(String product, int quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    void display() {
        System.out.println(product + " x " + quantity);
    }
}

class Order {
    private final Customer customer;
    private final List<OrderItem> items = new ArrayList<>();

    Order(Customer customer) {
        this.customer = customer;
    }

    void addItem(String product, int quantity) {
        items.add(new OrderItem(product, quantity));
    }

    void displayOrder() {
        System.out.println("Customer: " + customer.getName());
        System.out.println("Order items:");

        for (OrderItem item : items) {
            item.display();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Customer customer = new Customer("Neha");

        Order order = new Order(customer);
        order.addItem("Laptop", 1);
        order.addItem("Mouse", 2);

        order.displayOrder();
    }
}

Output:

Customer: Neha
Order items:
Laptop x 1
Mouse x 2

Explanation

  • Customer is created separately and passed into the order, illustrating aggregation.
  • Order creates its own OrderItem objects through addItem(), illustrating composition by design.
  • The private list hides the internal collection of line items.
  • The order exposes operations for adding and displaying items instead of exposing its internal list directly.

This is a simplified example. In a production application, an order may need persistent identifiers, validation, pricing, inventory checks, and database transaction management.

13. Advantages of Composition

  • Encapsulation: Internal objects can be hidden behind a public interface.
  • Modularity: Complex behavior can be divided into smaller classes.
  • Maintainability: Changes to a component may have limited impact on other classes.
  • Control: The owning class can manage how its components are created and used.
  • Flexible design: Classes can combine objects with different responsibilities instead of relying entirely on inheritance.

14. Advantages of Aggregation

  • Reusability: The same independently managed object may be used in multiple contexts when appropriate.
  • Flexibility: A referenced object can be replaced or reassigned according to application requirements.
  • Independent lifecycle: The part can exist before, during, and after its relationship with the whole.
  • Loose coupling: Classes can collaborate without owning each other's complete lifecycle.
  • Testability: Dependencies can be supplied from outside, including test implementations where suitable.

15. Common Mistakes to Avoid

  • Confusing composition with inheritance: Composition represents has-a; inheritance represents is-a.
  • Assuming Java has dedicated keywords: Java does not have special composition or aggregation keywords.
  • Assuming garbage collection follows ownership labels: Garbage collection is based on reachability.
  • Creating every dependency inside the constructor: This may be unsuitable when dependencies need to be shared or managed independently.
  • Exposing internal collections directly: Returning a mutable internal list can allow external code to bypass class rules.
  • Using composition for every relationship: Choose composition only when the domain implies ownership and lifecycle responsibility.
  • Ignoring null references: Aggregated dependencies should be validated or checked before use when they can be absent.
  • Assuming examples are universal rules: The same real-world entities can be modeled differently depending on business requirements.

16. Best Practices

  • Use composition when an object should own and manage its internal parts.
  • Use aggregation when objects should remain independently managed.
  • Prefer private fields to protect internal state.
  • Use constructor injection for required dependencies.
  • Use setter injection when changing or optionally supplying a dependency is part of the design.
  • Use interfaces where they help reduce coupling between components.
  • Keep classes focused on clear responsibilities.
  • Document ownership and lifecycle expectations when they are not obvious from the code.
  • Test behavior when dependencies are missing, replaced, or reused.

17. Practice Exercises

  1. Create a House class and a Room class to demonstrate composition.
  2. Create a School class and a Student class to demonstrate aggregation.
  3. Write a Library class that stores references to independently created Book objects.
  4. Create a Computer class containing a Motherboard object managed by the computer.
  5. Build a project-management example in which a Project references independently managed Developer objects.
  6. Modify an aggregation example to accept a dependency through a setter and handle a missing dependency safely.
  7. Explain why an order and its line items might be modeled using composition while an order and customer might be modeled using aggregation.

18. Interview Questions and Answers

Q1. What is composition in Java?

Composition is a strong whole-part relationship in which a containing object owns and manages its component objects as part of its internal structure.

Q2. What is aggregation in Java?

Aggregation is a weaker whole-part relationship in which one object references other objects that can exist independently of the containing object.

Q3. What is the main difference between composition and aggregation?

The key difference is ownership and lifecycle. Composition implies strong ownership of parts, whereas aggregation allows the referenced parts to have independent lifecycles.

Q4. Are composition and aggregation supported by special Java keywords?

No. They are object-oriented design concepts implemented using ordinary classes, object references, constructors, fields, and methods.

Q5. Can aggregation be implemented through a constructor?

Yes. An existing object can be passed into a constructor and stored as a field. This is a common way to establish an aggregation relationship.

Q6. Can composition be implemented using a list?

Yes. A class can own a collection of component objects, such as an order owning its line items. The class should manage the collection according to the intended lifecycle and business rules.

Q7. Does Java automatically destroy component objects when the containing object is deleted?

No. Java uses garbage collection. An object becomes eligible for garbage collection when it is no longer reachable, regardless of whether the program models the relationship as composition or aggregation.

Q8. What is the relationship between aggregation and association?

Aggregation is a specialized whole-part form of association. Association is the more general term for relationships between objects.

Q9. Why is composition often preferred over inheritance for code reuse?

Composition allows a class to reuse the behavior of other objects without creating a rigid inheritance hierarchy. It can improve flexibility and separation of responsibilities.

Q10. Give an example of aggregation.

A department referencing employee objects is a common example because employees can continue to exist independently of a particular department.

Q11. Give an example of composition.

An order owning its order-line objects is a common example when those line items are managed as parts of that order.

Q12. Can the same class participate in both composition and aggregation?

Yes. A class can own some objects while referencing other independently managed objects. The relationship depends on the role and ownership of each object.

19. Quick Revision Checklist

  • Composition is a strong has-a relationship.
  • Aggregation is a weaker has-a relationship.
  • Composition implies ownership and lifecycle responsibility for parts.
  • Aggregation allows referenced objects to exist independently.
  • Both relationships can be implemented using object references.
  • Java has no dedicated composition or aggregation keywords.
  • Garbage collection depends on reachability, not the relationship label.
  • Association is the general relationship; aggregation and composition are whole-part forms of association.
  • Inheritance models an is-a relationship.
  • Choose the relationship based on domain requirements, ownership, and lifecycle.

20. Conclusion

Composition and aggregation are important object-oriented design concepts in Java. Composition represents strong ownership of components, while aggregation represents a relationship with objects that remain independently managed. Both can help developers build modular, reusable, and maintainable applications.

Understanding these relationships helps you select appropriate class structures, manage dependencies, and model real-world business requirements accurately. Practice implementing both approaches and pay attention to object ownership, encapsulation, and lifecycle expectations.


Learn More with JustAcademy

Explore the Core Java Training Course to strengthen your understanding of object-oriented programming and Java application development.

Register for a Course Demo to learn more about the training program.

Visit JustAcademy to explore additional courses and learning resources.

Previous Next
whatsapp