What are the common reasons to make a constructor private in Java?
answer
- private = only this class can call new
- Utility class: private ctor blocks pointless instances (Math)
- Singleton: one instance, ctor blocks more
- Static factory: funnel new through named methods (valueOf, of)
- Without any ctor Java adds a public default one
basics
~20 sA 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 sMarking 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// 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
Knows private means only the same class can call new, and can name at least one use (utility class or singleton).
Lists all three uses (utility, singleton, factory) and knows that omitting a constructor yields a public default one.
Explains why static factories beat public constructors, recommends enum singletons, and hardens utility classes against reflection/self-instantiation.
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