A Detailed Tutorial on Destructors in Object-Oriented Programming

Afzal Badshah, PhD
4 min readOct 13, 2024

In object-oriented programming (OOP), managing memory and system resources is a critical task. When we create objects in a program, they occupy memory, and when they are no longer needed, that memory needs to be freed up. This process of releasing resources after their use is typically handled by destructors in many programming languages like C++. However, Java manages object cleanup differently.

In this tutorial, we’ll explore how destructors work in languages like C++, and how Java manages resource cleanup using the Garbage Collector and the finalize() method.

What is a Destructor?

A Destructor is a special method that is automatically invoked when an object is no longer needed or goes out of scope. Its primary responsibility is to release the memory or resources (like file handles, database connections, etc.) that the object was using during its lifetime.

In C++, destructors are explicitly defined by the programmer and called when the object is destroyed. However, in Java, destructors are not explicitly defined. Instead, Java provides a built-in garbage collection mechanism that automatically deallocates memory.

Destructor in C++ (for Comparison):

Here is how destructors work in C++:

class Car {
public:
// Constructor
Car() {
cout << "Car created." << endl;
}
    // Destructor
~Car() {
cout << "Car destroyed." << endl;
}
};
int main() {
Car myCar; // Constructor is called here
return 0; // Destructor is automatically called here
}

In C++, when the object myCar goes out of scope (at the end of the main() function), the destructor is called automatically to clean up resources.

Destructor-Like Behavior in Java

Java does not have destructors in the same way C++ does. Instead, Java uses a Garbage Collector (GC) to manage memory. The garbage collector automatically removes objects from memory when they are no longer referenced in the program.

This means that in most cases, Java developers do not need to manually free up memory or explicitly define destructors. However, there is a way to handle cleanup tasks before an object is destroyed, and that is by using the finalize() method.

The finalize() Method in Java:

The finalize() method is called by the garbage collector when it determines that there are no more references to an object. This method can be overridden to provide cleanup operations (like closing files or releasing resources) before the object is actually removed from memory.

Important Note: As of Java 9, the finalize() method is deprecated because of performance issues and unpredictability. Instead, Java provides the try-with-resources statement to handle resource cleanup.

Example of the finalize() Method:

class Car {
// Constructor
Car() {
System.out.println("Car created.");
}
    // finalize method (Deprecated in Java 9 and later)
@Override
protected void finalize() {
System.out.println("Car destroyed.");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car(); // Car object created
myCar = null; // Now the object is eligible for garbage collection
// Suggest garbage collection (not guaranteed)
System.gc(); // The finalize() method might be called here
}
}

Output:

Car created.
Car destroyed.

In the above example:

  • The Car object is created using the constructor.
  • The object is made eligible for garbage collection by setting myCar = null;.
  • The System.gc() method suggests the JVM to run garbage collection, which might result in the finalize() method being called.

However, it’s important to note that calling System.gc() does not guarantee immediate garbage collection. The timing of garbage collection is entirely up to the JVM.

Garbage Collection in Java

Java’s Garbage Collector (GC) automatically manages memory by freeing up space when objects are no longer needed. This eliminates the need for manual memory management, which is a common source of bugs in languages like C++.

How the Garbage Collector Works:

  1. Object Creation: When an object is created, memory is allocated to it on the heap.
  2. Reference Counting: As long as there are references to an object, it remains in memory.
  3. Garbage Collection: Once no references to an object exist, the garbage collector marks it for removal.
  4. Memory Cleanup: The garbage collector frees up the memory occupied by the object.

Key Differences Between Destructors in C++ and Java

AspectC++ DestructorJava Garbage Collection / finalize()DefinitionExplicitly defined by the programmerNo explicit destructors; finalize() can be overriddenInvocationAutomatically called when object goes out of scopeCalled when the garbage collector decides to destroy the object (not guaranteed)Memory ManagementManual memory management (with delete)Automatic memory management with the Garbage CollectorBest PracticeDefine destructors for resource cleanupUse try-with-resources for handling resourcesDeprecationNot applicablefinalize() is deprecated since Java 9

In Java, destructors are replaced by the automatic Garbage Collection mechanism, which is responsible for managing memory and resources. While Java used to rely on the finalize() method for object cleanup, this method is now deprecated in favor of the more efficient try-with-resources statement. This ensures that resources like file handles and database connections are properly closed once they are no longer needed.

Key Takeaways:

  1. No explicit destructors in Java: Memory management is handled by the garbage collector.
  2. finalize() is deprecated: Do not use finalize() for resource management; instead, use try-with-resources.
  3. Automatic cleanup: Java’s garbage collector ensures that objects are destroyed when they are no longer referenced, simplifying memory management for developers.

By understanding how Java handles object cleanup, developers can write efficient and resource-friendly code without worrying about memory leaks and resource mismanagement.

--

--

Afzal Badshah, PhD
Afzal Badshah, PhD

Written by Afzal Badshah, PhD

Dr Afzal Badshah focuses on academic skills, pedagogy (teaching skills) and life skills.