Back to Exceptions in Constructors & Static Init
Q1Question 1 of 2

What happens when an exception occurs in a constructor?

Key Concepts
  • If a constructor throws, the new expression never returns a reference and the variable stays null
  • The partially-constructed object is unreachable and will be garbage collected
  • Resources opened before the throw (file handles, connections, threads) are leaked because nobody holds a reference to close them
  • Fix: use temporary variables in try-catch inside the constructor, closing all resources in catch before rethrowing
  • Fix: use a static factory method that manages the resource lifecycle outside the constructor
  • The caller cannot access the half-built object, so there is no risk of using an inconsistent object

Definition

If a constructor throws, the new expression never returns a reference and the partially-constructed object is unreachable, but resources opened before the throw are leaked unless explicitly cleaned up.
  • If a constructor throws an exception, the new expression never returns a reference. The variable stays null (or the assignment never happens).
  • The partially-constructed object is unreachable and will be garbage collected. The caller cannot access the half-built object.
  • However, if the constructor opened resources (file handles, DB connections, threads) before the exception, those resources leak. They are allocated but nobody holds a reference to close them.
  • Fix: use try-catch inside the constructor to close resources on failure, or use a static factory method that manages resource lifecycle outside the constructor.

Building a new branch for National Bank of India: you install the vault (resource 1), then the alarm system (resource 2), then the cameras (resource 3). If camera installation fails, the branch is never opened to customers (object never returned). But the vault and alarm are already installed with nobody holding a key to disable them (resource leak).

Understanding the Concepts

What happens when a constructor throws?

The new expression never returns. The variable stays null, and the partially-constructed object is unreachable.

JAVA
package com.bank.demo;

public class ConstructorExceptionDemo {

    static class TradeProcessor {
        TradeProcessor(String config) {
            System.out.println("Step 1: config loaded");
            if (config.equals("BAD")) {
                throw new IllegalArgumentException("Invalid config: " + config);
            }
            System.out.println("Step 2: processor ready");
        }
    }

    public static void main(String[] args) {
        TradeProcessor processor = null;
        try {
            processor = new TradeProcessor("BAD");
        } catch (IllegalArgumentException e) {
            System.out.println("Caught: " + e.getMessage());
        }
        System.out.println("processor is: " + processor);
        // processor is null. The new expression never returned.
    }
}
TEXT
Step 1: config loaded
Caught: Invalid config: BAD
processor is: null

How do resource leaks happen in constructors?

If the constructor opens resources and then throws, those resources are allocated but nobody has a reference to close them.

JAVA
package com.bank.demo;

public class ConstructorLeakDemo {

    static class LeakyProcessor {
        private final String connection;
        private final String fileHandle;

        LeakyProcessor() {
            this.connection = "DB-Connection-Open";
            System.out.println("Opened: " + connection);

            this.fileHandle = "File-Handle-Open";
            System.out.println("Opened: " + fileHandle);

            // This line throws AFTER both resources are opened
            throw new RuntimeException("Schema validation failed");
            // connection and fileHandle are LEAKED.
            // Nobody has a reference to close them.
        }
    }

    public static void main(String[] args) {
        try {
            new LeakyProcessor();
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
            System.out.println("Resources are leaked. No reference to close them.");
        }
    }
}
TEXT
Opened: DB-Connection-Open
Opened: File-Handle-Open
Caught: Schema validation failed
Resources are leaked. No reference to close them.

How do you fix resource leaks in constructors?

Use try-catch with temporary variables to clean up on failure.

JAVA
package com.bank.demo;

public class SafeConstructorDemo {

    static class SafeProcessor {
        private final String connection;
        private final String fileHandle;

        SafeProcessor() {
            String tempConn = null;
            String tempFile = null;
            try {
                tempConn = "DB-Connection";
                System.out.println("Opened: " + tempConn);

                tempFile = "File-Handle";
                System.out.println("Opened: " + tempFile);

                // Simulate failure
                throw new RuntimeException("Validation failed");

            } catch (RuntimeException e) {
                // Clean up everything opened so far
                if (tempFile != null) System.out.println("Closed: " + tempFile);
                if (tempConn != null) System.out.println("Closed: " + tempConn);
                throw e;  // Rethrow after cleanup
            }
            // This line only reached on success:
            // this.connection = tempConn;
            // this.fileHandle = tempFile;
        }
    }

    public static void main(String[] args) {
        try {
            new SafeProcessor();
        } catch (RuntimeException e) {
            System.out.println("Caught: " + e.getMessage());
            System.out.println("Resources cleaned up before rethrowing.");
        }
    }
}
TEXT
Opened: DB-Connection
Opened: File-Handle
Closed: File-Handle
Closed: DB-Connection
Caught: Validation failed
Resources cleaned up before rethrowing.

What is the static factory method pattern?

A static factory manages the resource lifecycle outside the constructor, ensuring cleanup on failure.

JAVA
package com.bank.demo;

public class FactoryPatternDemo {

    static class TradeProcessor implements AutoCloseable {
        private final String connection;

        private TradeProcessor(String connection) {
            this.connection = connection;
        }

        static TradeProcessor create(String config) {
            String conn = "DB-Conn-" + config;
            System.out.println("Opened: " + conn);
            try {
                validate(config);
                return new TradeProcessor(conn);
            } catch (RuntimeException e) {
                System.out.println("Closed: " + conn);  // Cleanup on failure
                throw e;
            }
        }

        private static void validate(String config) {
            if (config.equals("BAD")) throw new RuntimeException("Invalid config");
        }

        @Override public void close() {
            System.out.println("Closed: " + connection);
        }

        public static void main(String[] args) {
            try {
                TradeProcessor p = TradeProcessor.create("BAD");
            } catch (RuntimeException e) {
                System.out.println("Caught: " + e.getMessage());
            }
        }
    }
}
TEXT
Opened: DB-Conn-BAD
Closed: DB-Conn-BAD
Caught: Invalid config

What should a senior engineer know?

  • Finalizers and Cleaners. A partially-constructed object whose constructor threw will NOT have its finalizer called (pre-Java 9) and should not rely on Cleaner (Java 9+) for resource cleanup.
  • Builder pattern. The Builder validates everything in build() before constructing the object, preventing partial construction entirely.
  • Spring beans. If a Spring @Service constructor throws, the ApplicationContext fails to start. Spring handles cleanup of already-constructed beans.

What are common interview follow-up questions?

  • Can the caller access a partially-constructed object? (No, the new expression never returns.)
  • What happens to the partially-constructed object? (It is unreachable and GC'd.)
  • How do you prevent resource leaks in constructors? (try-catch with cleanup, or static factory.)
  • Is the object's finalizer called if the constructor throws? (No.)

Visual Overview

DIAGRAM
  new TradeProcessor(config)
       │
       ├── Step 1: open connection    (resource allocated)
       ├── Step 2: open file handle   (resource allocated)
       ├── Step 3: validate           (throws!)
       │
       ▼
  Constructor throws
       │
       ├── new expression NEVER returns
       ├── variable stays null
       ├── Object unreachable (GC'd)
       └── connection + file handle: LEAKED

  Fix: try-catch in constructor
       │
       ├── catch: close file handle
       ├── catch: close connection
       └── rethrow after cleanup

Key Takeaway

When a constructor throws an exception, the new expression never returns. The variable stays null and the partially-constructed object is unreachable, so the caller cannot use an inconsistent object. However, resources opened before the throw (database connections, file handles, threads) are leaked because nobody holds a reference to close them.

At National Bank of India, a BatchSettlementProcessor constructor opens a DB connection, opens a file, then validates the schema. If validation throws, the connection and file handle are leaked. After 500 failed attempts, the connection pool is exhausted and the file descriptor limit is hit, hanging the entire system.

The fix is to use temporary variables with try-catch inside the constructor, closing all resources in the catch block before rethrowing. The static factory method pattern is even cleaner: the factory manages the resource lifecycle and only calls the private constructor when everything is validated.

Remember one sentence: a throwing constructor never returns an object reference, but resources opened before the throw are leaked unless you explicitly clean them up.

---

Share
Use ← → arrow keys to navigate