Skip to content

Constructor

1. Define a constructor. Discuss its special properties and advantages.

A constructor in Java is a special type of method that is automatically called when an object of a class is created. Its primary job is to initialize the state of the new object, ensuring it starts in a valid and consistent condition. Think of it as a "setup wizard" for an object.

A constructor has several special properties that distinguish it from a regular method:

  • Same Name as the Class: A constructor's name must be exactly the same as the name of the class it belongs to.

  • No Return Type: Constructors do not have a return type, not even void. Their implicit job is to return the newly created object instance.

  • Automatic Invocation: Proper Constructor is invoked automatically by the new keyword during object creation, no need to call a constructor directly.

  • Default Constructor: If no constructor is defined in the class, the Java compiler will automatically provide a parameter-less "default constructor". The moment any constructor is defined, this automatic one is no longer supplied.

The main advantages of using constructors are:

  • Guaranteed Initialization: They ensure that an object is properly initialized with default or specific values right at creation, preventing errors like NullPointerException from uninitialized fields.

  • Code Simplicity: They centralize the object setup logic in one place, making the code cleaner and easier to read. You can create a fully configured object in a single line.

  • Flexibility through Overloading: You can define multiple constructors (overload them) to provide different ways of creating and initializing an object, which enhances the flexibility of your class.


2. Discuss the use and purpose of the this keyword in Java.

The this keyword in Java is a reference variable that refers to the current object—the instance whose method or constructor is being called.

The most common uses of this are:

  • Disambiguating Instance Variables: This is the most frequent use to eliminate ambiguity. When a constructor or method parameter has the same name as an instance variable, this is used to specify that you are referring to the instance variable.
java
class Employee {
	private String name; // Instance variable

	// The 'name' parameter shadows the instance variable 'name'.
	public Employee(String name) {
		this.name = name;
	// "this.name" is the instance variable.
	// "name" is the parameter passed.
	}
}
  • Invoking an Overloaded Constructor (Constructor Chaining): From within a constructor, this(...) can be called to call another constructor in the same class. This is great for reducing code duplication. The this(...) call must be the very first statement in the constructor.
java
class Box {

	public Box() {
		this(1, 1, 1); // Calls the constructor below
	}

	public Box(double width, double height, double depth) {
		// ... initialization logic ...
	}
}
  • Passing the Current Object as an Argument: You can pass the current object as a parameter to another method.
java
class EventManager {

	public void register(Event event) {
	// Passes the current Event object to the manager.
		someLogger.logEvent(this);
	}
}
  • Returning the Current Instance from a Method: This is useful for creating "fluent interfaces" where you can chain method calls together.
java
class EmailBuilder {
	public EmailBuilder setRecipient(String address) {
		// ... logic ...
		return this; 
		// Return the current object to allow chaining
	}

	public EmailBuilder setSubject(String subject) {
		// ... logic ...
		return this;
	}
}
// Usage: new EmailBuilder().setRecipient("...").setSubject("...");

3. Explain how constructors can be overloaded with the help of an example.

Constructor overloading is the practice of having more than one constructor within the same class. Just like method overloading, each constructor must have a different parameter list (either a different number of parameters, different types of parameters, or both).

This gives multiple, flexible ways to create an object based on parameters passed during instantiation.

Example: A Box Class with Overloaded Constructors

A Box class that can be instantiated as a default box, as a perfect cube, or as a box with specific dimensions.

java
// A class with overloaded constructors
class Box {
    double width;
    double height;
    double depth;

// Constructor 1: Three parameters (for a custom box)
    Box(double w, double h, double d) {
        System.out.println("Three-parameter constructor called.");
        this.width = w;
        this.height = h;
        this.depth = d;
    }

// Constructor 2: One parameter (for creating a cube)
    Box(double dimension) {
        this(dimension, dimension, dimension); 
        // Calls the three-parameter constructor
        System.out.println("Cube constructor called.");
    }

// Constructor 3: No parameters (default box)
    Box() {
        this(-1, -1, -1); 
        // Calls the three-parameter constructor
        System.out.println("Default constructor called.");
    }

    // A method to calculate the volume of the box
    double volume() {
        return width * height * depth;
    }
}

class DemoBox {
    public static void main(String[] args) {

        Box defaultBox = new Box();       
        Box cube = new Box(7);            
        Box customBox = new Box(10, 20, 15); 

        System.out.println("\n--- Box Volumes ---");

		System.out.println("Volume of defaultBox is " 
	        + defaultBox.volume());

		System.out.println("Volume of cube is " 
	        + cube.volume());

		System.out.println("Volume of customBox is " 
	        + customBox.volume());
    }
}

Output:

Three-parameter constructor called.
Default constructor called.

Three-parameter constructor called.
Cube constructor called.

Three-parameter constructor called.

--- Box Volumes ---
Volume of defaultBox is -1.0
Volume of cube is 343.0
Volume of customBox is 3000.0

4. The Swapper Class

A Swapper class to hold and swap two integer values. The SwapperDemo class then creates an instance of Swapper, prints the initial values, calls the swap() method, and prints the new values to confirm the swap was successful.

java
class Swapper {
    private int x;
    private int y;

    public Swapper(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void swap() {
        int temp = this.x; 
        this.x = this.y;   
        this.y = temp; 
    }
}


public class SwapperDemo {
    public static void main(String[] args) {

		Swapper mySwapper = new Swapper(10, 20);

        System.out.println("Before swap:");
        System.out.println("x = " + mySwapper.getX()); 
	        // Should be 10
		System.out.println("y = " + mySwapper.getY()); 
			// Should be 20

        mySwapper.swap();

        System.out.println("After swap:");
        System.out.println("x = " + mySwapper.getX()); 
	        // Should be 20
        System.out.println("y = " + mySwapper.getY()); 
	        // Should be 10
    }
}

5. The Employee Class

An Employee class to store employee data and calculate net salary based on the given business rules. The main program in the EmployeeDemo class reads an employee's basic details from the user, calculates the salary components, and prints a formatted report.

java
import java.util.Scanner;

class Employee {
    // Data members
    private int emp_no;
    private String emp_name;
    private double basic;
    
    private double da;
    private double IT;
    private double Net_sal;

    Employee(int empNo, String empName, double basicPay) {
        this.emp_no = empNo;
        this.emp_name = empName;
        this.basic = basicPay;
    }

    public void calculateNetSalary() {
        // DA is 60% of basic pay
        this.da = 0.60 * this.basic;

        // IT is 20% or 30% based on basic pay
        if (this.basic < 1500000) {
            this.IT = 0.20 * this.basic;
        } else {
            this.IT = 0.30 * this.basic;
        }

        // Net Salary = Basic + DA - IT
        this.Net_sal = this.basic + this.da - this.IT;
    }

    public void printData() {
        System.out.println("\n--- Employee Salary Details ---");
        System.out.println("Employee Number: " + emp_no);
        System.out.println("Employee Name:   " + emp_name);
        System.out.println("-------------------------------");
        System.out.printf("Basic Salary:    %,.2f\n", basic);
        System.out.printf("Dearness (DA):   %,.2f\n", da);
        System.out.printf("Income Tax (IT): %,.2f\n", IT);
        System.out.println("-------------------------------");
        System.out.printf("Net Salary:      %,.2f\n", Net_sal);
        System.out.println("-------------------------------");
    }
}

public class EmployeeDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("Enter Employee Number: ");
        int empNo = scanner.nextInt();
        
        scanner.nextLine(); // Consume newline character

        System.out.print("Enter Employee Name: ");
        String empName = scanner.nextLine();

        System.out.print("Enter Basic Salary: ");
        double basicPay = scanner.nextDouble();

        scanner.close();
        
        // 1. Initialize the employee object with the data
		Employee employee = new Employee(empNo, empName, basicPay);
		
        // 2. Calculate the net salary
        employee.calculateNetSalary();

        // 3. Print the final report
        employee.printData();
    }
}

6. What is Garbage Collection in Java?

Garbage Collection (GC) is Java's automatic memory management process. It's like a built-in cleanup service that runs in the background within the Java Virtual Machine (JVM).

Its job is to automatically identify and reclaim memory that is being used by objects that are no longer needed by the application. An object becomes "garbage" or eligible for collection when it's no longer reachable—that is, when there are no active references pointing to it.

This happens when:

  • A reference variable is set to null.

  • A reference variable is reassigned to point to another object.

  • An object was created in a method, and the method has finished executing.

Key Advantages:

  • Prevents Memory Leaks: By automatically cleaning up unused objects, the GC prevents common memory leak issues where memory is allocated but never freed.

  • Simplifies Development: Programmers don't have to manually write code to deallocate memory, unlike in languages such as C or C++. This makes Java code safer and easier to write.

The garbage collection process is non-deterministic, meaning you can't be certain exactly when it will run. While you can suggest that the JVM run the GC with System.gc(), there is no guarantee it will do so immediately.


7. What does the finalize() method do? Explain its role with an example.

Important Note: The finalize() method has been deprecated since Java 9 and is strongly discouraged. Its use is unreliable and can cause performance issues.

Modern Java applications should use alternatives like the try-with-resources statement or the java.lang.ref.Cleaner API.

The finalize() method is a protected method of the java.lang.Object class. Its original purpose was to be a hook that the Garbage Collector would call on an object just before reclaiming its memory. The intended use was to perform last-minute cleanup tasks, especially for releasing non-Java (native) resources like file handles or database connections that the GC doesn't manage.

Role and Problems:

  • Unreliable: There is no guarantee that finalize() will ever be called. A program might terminate before the GC gets a chance to run on a particular object.

  • Performance Penalty: Objects with a finalize() method are more complex for the GC to process, which can slow down memory reclamation.

Example (for demonstration purposes only):

The following example shows how finalize() was intended to work. Do not use this pattern in modern code.

java
class ResourceHolder {
    private String name;

    public ResourceHolder(String name) {
        this.name = name;
        System.out.println(this.name + " resource created.");
    }

	//The GC calls this before destroying the object.
	@Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Finalizing: " 
	            + this.name + " is being cleaned up!");
        } finally {
            super.finalize(); 
	        // Always call the superclass's finalize
        }
    }
}

public class FinalizeDemo {
    public static void main(String[] args) {
    
        new ResourceHolder("Resource 1");
        new ResourceHolder("Resource 2");
        // no reference is stored. immediately eligible for GC

        // Suggest to the JVM to run the GC.
        // This is not a guarantee that it will run.
        System.gc();

        System.out.println("Program finished.");
    }
}

Possible Output:

Resource 1 resource created.
Resource 2 resource created.
Finalizing: Resource 2 is being cleaned up!
Finalizing: Resource 1 is being cleaned up!
Program finished.

Made with ❤️ for students, by a fellow learner.