skip to content

What are the common reasons to make a constructor private in Java?

level: middleimportance: should knowfreq 60%

answer

  1. private = only this class can call new
  2. Utility class: private ctor blocks pointless instances (Math)
  3. Singleton: one instance, ctor blocks more
  4. Static factory: funnel new through named methods (valueOf, of)
  5. Without any ctor Java adds a public default one

basics

~20 s

A private constructor stops other code from creating objects with new. You use it to force creation through factory methods, to make a singleton (only one instance), or for utility classes that hold only static members and should never be instantiated.

solid answer

~40 s

Marking a constructor `private` means only code inside the same class can call it; outside code cannot use `new`. The three classic uses are: (1) **Utility/helper classes** that contain only static methods and constants — a private no-arg constructor prevents pointless instantiation (e.g. `java.lang.Math`). (2) **Singletons** — the class creates and hands out a single shared instance via a static accessor or `enum`, and the private constructor guarantees no one else makes another. (3) **Static factory methods** — instead of `new`, callers use named methods like `Optional.of(x)` or `Integer.valueOf(x)`; the private (or package-private) constructor channels all creation through the factory, which gains naming, caching, and the freedom to return a subtype. The unifying theme: a private constructor lets the class take full control of how (and whether) its instances are created.

code

java · 16 lines
java
// Utility class: private ctor prevents instantiation
public final class StringUtils {
    private StringUtils() {
        throw new AssertionError("no instances");
    }
    public static boolean isBlank(String s) {
        return s == null || s.isBlank();
    }
}

// Static factory: private ctor funnels creation
public final class Money {
    private final long cents;
    private Money(long cents) { this.cents = cents; }
    public static Money ofCents(long cents) { return new Money(cents); }
}

go deeper

for a junior

Knows private means only the same class can call new, and can name at least one use (utility class or singleton).

for a middle

Lists all three uses (utility, singleton, factory) and knows that omitting a constructor yields a public default one.

for a senior

Explains why static factories beat public constructors, recommends enum singletons, and hardens utility classes against reflection/self-instantiation.

for a principal

Guides API design around controlled instantiation (interfaces + hidden impls, factory naming conventions), weighs the testability/subclassing trade-offs of private constructors, and standardizes patterns across a codebase.

## Background: who can call a constructor? An object is normally created with `new ClassName(...)`, which invokes a **constructor**. Like any member, a constructor has an **access modifier** controlling who can call it: `public` (anyone), `protected` (subclasses + same package), package-private (same package), or `private` (only code *inside the same class*). When you make a constructor `private`, ordinary outside code can no longer write `new ClassName(...)`. That sounds limiting, but it is a powerful design tool: the class itself decides exactly how — and whether — instances come into existence. ## Use 1: Utility / helper classes (no instances at all) A **utility class** holds only `static` members — methods and constants — and has no per-object state. Examples in the JDK: `java.lang.Math`, `java.util.Collections`, `java.util.Arrays`. It never makes sense to create an instance of `Math`. To prevent it, give the class a single private no-arg constructor: ```java public final class MathUtils { private MathUtils() { throw new AssertionError("No MathUtils instances for you!"); } public static int square(int n) { return n * n; } } ``` Why this matters: if you write *no* constructor, Java inserts a **default public no-arg constructor**, so people *could* instantiate the class. The private constructor suppresses that. Throwing inside it also defends against the class calling `new` on itself by accident (and via reflection from within). Marking the class `final` documents that it is not meant to be subclassed either. ## Use 2: Singletons (exactly one instance) A **singleton** is a class designed to have exactly one instance, shared everywhere. The class creates that single instance and exposes it; the private constructor stops anyone else from making a second one. ```java public final class Registry { private static final Registry INSTANCE = new Registry(); private Registry() { } // nobody else can call this public static Registry getInstance() { return INSTANCE; } } ``` The most robust singleton, recommended in *Effective Java*, is actually an `enum` with one constant — it gives you serialization safety and reflection safety for free, and an enum's constructor is implicitly private. ## Use 3: Static factory methods A **static factory method** is a static method that returns an instance, used *instead of* a public constructor. The constructor is made private (or package-private) so all creation funnels through the factory. JDK examples: `Integer.valueOf(42)`, `Optional.of(x)`, `List.of(...)`, `LocalDate.of(2026, 6, 20)`. Why funnel creation through a factory rather than expose `new`? - **Names:** a factory has a descriptive name (`BigInteger.probablePrime(...)`), unlike constructors which all share the class name. - **Caching / no required new object:** `Integer.valueOf` returns cached instances for small values; `Boolean.valueOf` never makes a new object. - **Return-type flexibility:** a factory can return a subtype or a hidden implementation class the caller doesn't know about (`Collections.emptyList()`), enabling encapsulation and interface-based APIs. - **One place to enforce invariants** before the object escapes. ```java public final class Color { private final int rgb; private Color(int rgb) { this.rgb = rgb; } // private public static Color of(int rgb) { return new Color(rgb); } public static Color black() { return new Color(0x000000); } } ``` ## The unifying idea In all three cases the private constructor is about **control over instantiation**: no instances (utility), one instance (singleton), or controlled/named instances (factory). It is one of the simplest yet most expressive design levers in the language.

  • Why is a private constructor not enough on its own to prevent ALL instantiation of a utility class?
    Reflection (setAccessible(true)) can still invoke a private constructor, and code inside the class itself can call new. Throwing an AssertionError from the body, and not exposing any factory, hardens it against both.
  • What are the advantages of static factory methods over public constructors?
    They have descriptive names, can return cached instances (need not create a new object each call), can return a subtype/hidden implementation, and centralize invariant checks. The downsides: classes with only private constructors can't be subclassed, and factory methods are harder to spot in docs than constructors.

saying these in an interview costs you the question

  • Forgetting that Java adds a public default constructor when you declare none, leaving a utility class instantiable
  • Thinking a private constructor makes a class impossible to instantiate even via reflection
  • Confusing 'private constructor' with 'final class' — they solve different problems (instantiation vs subclassing)
  • Implementing a hand-rolled singleton when an enum singleton would be safer

context