Composition in Java is one of the core concepts of object-oriented programming. It is different from the inheritance in Java.
Inheritance is defined as Is-A relationship whereas, composition is defined as Has-A relationship. Both composition and inheritance are design techniques used for the purpose of code reusability.
Composition is a more specialized and stronger form of aggregation. In composition, the child object does not have its own independent life cycle. If the parent object is destroyed, the child object is also destroyed automatically because the child object cannot exist without the parent object.
In simple words, composition can be defined as a relationship in which a parent object contains a child object, and the child object cannot exist on its own without having the existence of the parent object.
You can achieve composition in Java by using an instance variable that refers to other objects. Let’s understand the basic meaning of composition with help of realtime examples.
Real-Time Example of Composition in Java
1. House and Room
We live in a house. A house can contain many rooms. However, a room does not have an independent existence without a house, and a room cannot belong to two different houses at the same time.
If the house is destroyed, its rooms will also be destroyed. Therefore, we can say that a room is a PART-OF a house. This represents composition because the life cycle of the room depends on the life cycle of the house.
2. Car and Engine
Another real-time example of composition in Java is the relationship between a car and an engine. A car has an engine. In other words, an engine is a PART-OF a car.
Here, the car is the whole object, and the engine is a part of that object. If the car is destroyed, its engine will also be destroyed. Therefore, without the existence of the car, there is no meaningful life of an engine. The life cycle of the engine is strongly dependent on the life cycle of the car.
Example of Composition in Java
Let’s understand the composition between Car and Engine programmatically with the help of an example program. Look at the following program code to understand better.
Example:
class Engine
{
private String type;
private int horsePower;
Engine(String type, int horsePower) {
this.type = type;
this.horsePower = horsePower;
}
public String getType() {
return type;
}
public int getHorsePower() {
return horsePower;
}
public void setType(String type){
this.type = type;
}
public void setHorsePower(int horsePower){
this.horsePower = horsePower;
}
}
class Car
{
private final String name;
private final Engine engine; // Composition.
public Car(String name, Engine engine) {
this.name = name;
this.engine = engine;
}
public String getName() {
return name;
}
public Engine getEngine() {
return engine;
}
}
public class Main {
public static void main(String[] args)
{
// Creating an object of Engine class.
Engine engn = new Engine("Petrol", 300);
// Creating an object of Car class.
Car car = new Car("Alto", engn);
System.out.println("Name of car: " +car.getName()+
"\n" +"Type of engine: " +engn.getType()+
"\n" + "Horse power of Engine: " +engn.getHorsePower());
}
}Output:
Name of car: Alto Type of engine: Petrol Horse power of Engine: 300
In this example:
- We have created a class Engine that contains two private attributes: type (string) and horsePower (integer). It has a constructor that takes two parameters, type and horsePower, and initializes the attributes with these values.
- In addition to it, there are getter and setter methods for both attributes to retrieve and update their values.
- Then, we have created a class Car containing two private attributes: name (string) and engine (of class type Engine). The class has a constructor that takes a name and an engine object as parameters.
- The name attribute is assigned the provided name, and the engine attribute is assigned the provided engine object. The class contains getter methods for both attributes to retrieve their values.
- We have defined a class Test that contains the main method, which serves as the entry point for the program. Inside the main method, we have created an instance of the Engine class by passing the values “Petrol” and 300 to its constructor.
- Then, we have created an instance of the Car class by passing the values “Alto” and the previously created Engine instance to its constructor. This shows the concept of composition, where the Car class contains an instance of the Engine class as one of its attributes.
- At last, the program code prints out the name of the car, type of engine, and horse power of the engine using the getter methods of the Car and Engine classes.
Features of Composition in Java
There are several important features of composition in Java, which are as follows:
- Composition represents a has-a relationship in Java. In other words, it represents PART-OF relationship.
- It is a more restrictive and stronger form of aggregation.
- In composition, both entities are strongly associated with each other.
- A composition relationship between two entities occurs when a parent object contains a child object (composed objects), and the child object cannot exist independently without the parent object.
- It can be achieved by using an instance variable that refers to other objects.
Advantages of Using Composition Over Inheritance
There are several benefits of using composition in Java over inheritance. They are as follows:
- Composition is better than inheritance because it allows to reuse of code and provides visibility control on objects.
- Java doesn’t allow multiple inheritance but by using composition we can achieve it easily.
- Composition grants better test-ability of a class.
- By using composition, we can easily replace the implementation of a composed class with a better and improved version.
- Composition allows the changing of member objects at runtime so that we can dynamically change the behavior of our program.
Difference Between Aggrgation and Composition in Java
The main difference between aggregation and composition is:
- Aggregation represents a Has-A relationship between two objects where both objects can exist independently and have their own life cycle.
- Composition represents a Has-A relationship where the contained object cannot exist independently without the parent object.




