Aggregation: whole-part relationships with independent lifecycles
Learn aggregation in OOP: a has-a relationship where the part can exist independently of the whole, with Java examples and UML notation.
Most candidates treat aggregation and composition as the same thing. They draw a diamond on a UML diagram and move on. But the distinction matters: it tells you who controls the lifecycle of the contained object, and getting that wrong leads to bugs where deleting a parent either leaks orphans or accidentally destroys shared data.
Aggregation is a "has-a" relationship where the part can outlive the whole. A Department has Employee objects, but firing the department does not erase the employees from existence. They walk over to another department. That independence is what separates aggregation from composition, and it is the single most important thing to communicate in an interview.
What Is Aggregation
Aggregation means the whole contains references to its parts, but does not own their lifecycles. The parts are created somewhere else, passed in, and continue to exist if the whole is destroyed.
Think of a university department. The department groups professors together under one roof, but the professors existed before the department was formed and will continue to exist if the department is dissolved. The department is a container, not a factory.
Compare this to a House and its Room objects. Demolish the house, and the rooms are gone. That is composition. The room has no independent existence outside the house.
For your interview: aggregation means "I hold references to things I did not create and will not destroy." Composition means "I create these things, and they die with me."
Aggregation is a specialized association
Every aggregation is an association with added "whole-part" semantics. The part can exist independently, but the whole groups parts into a meaningful collection. Think of it as association plus the sentence "is part of."
UML Notation
Aggregation uses a hollow (open) diamond on the "whole" side of the relationship. The diamond sits on the class that acts as the container. The line points toward the part.
Contrast this with the two other diamond types:
| Symbol | UML Name | Meaning | Diamond |
|---|---|---|---|
o-- | Aggregation | Whole groups parts, parts survive | Hollow (open) |
*-- | Composition | Whole owns parts, parts die with whole | Filled (solid) |
--> | Association | Objects reference each other, no ownership | No diamond |
The hollow diamond is the visual cue interviewers look for. If you draw a filled diamond when you mean aggregation, you are signaling that the part cannot exist alone, which changes the design conversation entirely.
Notice the pattern: University aggregates Department, Department aggregates Professor. Professors can move between departments. They can even belong to two departments simultaneously (cross-listed appointments). Rooms cannot move between buildings. That is the visual shorthand.
Aggregation vs Composition
This is the question you will get in interviews. The distinction comes down to one thing: what happens when the parent is deleted?
| Dimension | Aggregation | Composition |
|---|---|---|
| UML diamond | Hollow β | Filled β |
| Lifecycle | Part exists independently | Part dies with the whole |
| Who creates the part? | External code, passed in | The whole creates it internally |
| Shared ownership? | Yes, part can belong to multiple wholes | No, part belongs to exactly one whole |
| Deletion cascade | No cascade | Cascade delete |
| Java signal | Constructor receives the part | Constructor creates the part with new |
| Real example | Team has Players (players exist without team) | Invoice has LineItems (line items are meaningless without invoice) |
The practical test I use: can you take the part out of the whole and hand it to someone else? If yes, aggregation. If the part makes no sense outside the whole (what is an OrderLine without an Order?), it is composition.
The constructor test is not absolute
Some code creates parts inside the constructor for convenience but still treats them as independent (e.g., a default empty list). The real test is domain intent: does the part have meaning and identity outside the whole? Code structure is a hint, not a proof.
Implementation
// Employee exists independently. It is not created by Department
// and is not destroyed when Department is removed.
// An employee can move between departments freely.
public class Employee {
private final String id;
private final String name;
private String role;
public Employee(String id, String name, String role) {
this.id = id;
this.name = name;
this.role = role;
}
public String getId() { return id; }
public String getName() { return name; }
public String getRole() { return role; }
@Override
public String toString() {
return name + " (" + role + ")";
}
}The key observation in Main.java: setting engineering = null garbage-collects the department object, but alice and carol remain fully functional. They are not tied to the department's lifecycle. Compare this to composition, where you would expect child objects to be cleaned up (or become invalid) when the parent is destroyed.
I also want to highlight the Professor shared across departments. In composition, a part belongs to exactly one parent. In aggregation, the same part can appear in multiple wholes. Dr. Smith teaches in both CS and Math. That shared ownership is one of the clearest signals that you are looking at aggregation, not composition.
Interview signal: look for the constructor
If the "whole" receives the part as a constructor or method parameter, it is probably aggregation. If the whole calls new Part() internally, it is probably composition. This is a quick heuristic, not a law, but it is right 90% of the time.
When to Use Aggregation
So when does aggregation actually matter in a design interview?
The part has independent identity. Employees have IDs, names, and careers that exist outside any department. Songs exist outside any playlist. If the part has a primary key or a meaningful identity of its own, aggregation is your default.
The part can be shared. A professor teaches in multiple departments. A song appears in multiple playlists. Composition forbids sharing because the parent "owns" the child. If sharing is a requirement, aggregation is the only correct choice.
The part's lifecycle is managed elsewhere. Employees are hired by HR, not by the department. Players are signed by the club, not by the team roster. If some other system or process creates and destroys the part, the whole is just holding a reference.
You want loose coupling. Aggregation means the whole can be tested with mock parts. The department does not need to know how to construct an employee. This makes unit testing simpler and keeps dependencies flowing in one direction.
Here is the honest answer: in most real codebases, the distinction between aggregation and plain association is subtle. The practical difference shows up in database design (cascade delete or not), serialization (deep copy or reference), and garbage collection (preventing memory leaks by clearing references). In interviews, the distinction between aggregation and composition is what matters most.
Common Mistakes
Mistake 1: Confusing aggregation with composition.
"A Team has Player objects, so it must be composition." No. Players exist independently of any team. They can be free agents, traded, or retired. Dissolving the team does not erase the players. The lifecycle independence makes this aggregation.
Mistake 2: Drawing a filled diamond when you mean hollow.
In UML, β (filled) means composition and β (hollow) means aggregation. Interviewers who know UML will interpret a filled diamond as "the child dies with the parent." If you mean aggregation, draw it hollow or explicitly say "the part exists independently."
Mistake 3: Circular aggregation chains.
If A aggregates B and B aggregates A, you have a circular dependency. Neither can be the "whole." This usually means the relationship is plain association, not aggregation. Aggregation implies a directional whole-part hierarchy.
Mistake 4: Treating aggregation as weak composition. Some developers treat aggregation as "composition but the child might survive." That framing is backwards. Aggregation is not weakened composition. It is strengthened association. The part was always independent; the whole just groups it.
Mistake 5: Not clearing references when the whole is done.
If a Department object is removed but its List<Employee> still holds strong references, those employees cannot be garbage collected even if nothing else references them. In languages with garbage collection, clearing the list in a cleanup method prevents subtle memory leaks.
Shared parts and cascade delete
In database terms, aggregation means you should NOT use ON DELETE CASCADE on the foreign key. If you delete the department row, the employee rows must survive. Using cascade delete on an aggregation relationship silently converts it into composition at the database layer, which contradicts your domain model.
Test Your Understanding
Quick Recap
- Aggregation is a "has-a" relationship where the part exists independently of the whole. The whole groups parts but does not own their lifecycles.
- UML notation: hollow (open) diamond
βon the whole side. Filled diamondβis composition, not aggregation. - The lifecycle test: delete the parent. If the child survives and is still meaningful, it is aggregation. If the child is destroyed or meaningless, it is composition.
- In Java, the signal is that the whole receives parts from outside (constructor parameter, setter) rather than creating them with
new. - Aggregated parts can be shared across multiple wholes. A professor in two departments is aggregation. A room in one building is composition.
- In database design, aggregation means no cascade delete. Use
SET NULLorRESTRICTon the foreign key. - In interviews, lead with the lifecycle test. It is the fastest way to distinguish aggregation from composition and immediately demonstrates that you understand the semantics, not just the syntax.