00:00

Private Constructor in Java – Uses and Examples

A private constructor is a constructor that can only be called from inside its own class. Other classes cannot write new MyClass(). That sounds odd at first, but it is how Java controls who creates objects and how many are created.

This tutorial explains the main uses of private constructors, utility classes, singletons, static factory methods and enums, with runnable examples, and shows how they affect inheritance.

1. What a Private Constructor Does

Marking a constructor private means only code in the same class (including its nested classes) can call it. Any other class gets a compile error:

javac output
Main.java:2: error: Config() has private access in Config
public class Main { public static void main(String[] a) { new Config(); } }
                                                          ^
1 error

The class decides for itself when objects are created, usually through a static method.

2. Use 1: Utility Classes

A class that contains only static methods and constants, such as java.lang.Math or java.util.Collections, should never be instantiated. A private constructor makes that impossible, and throwing an AssertionError inside it also stops accidental calls from within the class:

UtilityClass.java
public class UtilityClass {
    // A utility class: only static members, never instantiated
    static final class MathUtils {
        private MathUtils() {
            throw new AssertionError("MathUtils cannot be instantiated");
        }
        static int square(int n) { return n * n; }
        static boolean isEven(int n) { return n % 2 == 0; }
    }

    public static void main(String[] args) {
        System.out.println("square(7) = " + MathUtils.square(7));
        System.out.println("isEven(10) = " + MathUtils.isEven(10));
        // new MathUtils();   // would compile here (same outer class) but throws AssertionError
    }
}
Output
square(7) = 49
isEven(10) = true

Without the private constructor, the compiler would add a public default constructor and new MathUtils() would compile everywhere.

3. Use 2: The Singleton Pattern

A singleton is a class with exactly one instance, such as a configuration registry or a connection manager. The private constructor prevents extra instances, and a static method returns the single one:

Singleton.java
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private int requests;

    private Singleton() {                       // nobody else can call new Singleton()
        System.out.println("Singleton created");
    }

    public static Singleton getInstance() { return INSTANCE; }

    public int handleRequest() { return ++requests; }

    public static void main(String[] args) {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        a.handleRequest();
        System.out.println("requests seen by b: " + b.handleRequest());
        System.out.println("same instance: " + (a == b));
    }
}
Output
Singleton created
requests seen by b: 2
same instance: true

Here the instance is created eagerly when the class loads, which is simple and thread-safe. Singletons create hidden global state, so use them sparingly; dependency injection frameworks such as Spring manage single instances for you.

4. Use 3: Static Factory Methods

Constructors all share the class's name, so two constructors taking one double cannot be told apart. With a private constructor and named static factories, each way of creating an object gets a clear name:

FactoryMethods.java
public class FactoryMethods {
    static final class Temperature {
        private final double celsius;

        private Temperature(double celsius) { this.celsius = celsius; }

        // Named static factories are clearer than overloaded constructors with the same parameter type
        static Temperature ofCelsius(double c) { return new Temperature(c); }
        static Temperature ofFahrenheit(double f) { return new Temperature((f - 32) * 5 / 9); }
        static Temperature ofKelvin(double k) { return new Temperature(k - 273.15); }

        @Override public String toString() { return String.format("%.1f °C", celsius); }
    }

    public static void main(String[] args) {
        System.out.println(Temperature.ofCelsius(25));
        System.out.println(Temperature.ofFahrenheit(98.6));
        System.out.println(Temperature.ofKelvin(300));
    }
}
Output
25.0 °C
37.0 °C
26.9 °C

Factories can also return cached instances (Integer.valueOf()), choose a subclass (List.of()), or validate input before creating anything. The JDK uses this style widely: LocalDate.of(), Optional.of(), Path.of().

5. Use 4: Enums

Enum constructors are always private, whether or not you write the keyword. Only the constants listed in the enum can ever exist, which makes a single-constant enum the simplest and safest way to write a singleton:

EnumSingleton.java
public class EnumSingleton {
    // Enum constructors are always private; an enum with one constant is a simple, safe singleton
    enum AppConfig {
        INSTANCE;

        private final String environment;

        AppConfig() {                       // implicitly private
            environment = "production";
        }

        String environment() { return environment; }
    }

    public static void main(String[] args) {
        System.out.println(AppConfig.INSTANCE.environment());
        System.out.println(AppConfig.INSTANCE == AppConfig.valueOf("INSTANCE"));
    }
}
Output
production
true

Enum singletons are protected against reflection and serialization tricks that can break a class-based singleton.

6. Private Constructors and Inheritance

  • A subclass constructor must call a parent constructor. If all of the parent's constructors are private, no outside class can extend it, so a private constructor effectively makes the class non-extendable.
  • Nested classes are an exception: they can call the outer class's private constructor, so a class can allow subclasses only inside itself.
  • To clearly prevent inheritance, also declare the class final; or use sealed classes (Java 17) to list exactly which subclasses are allowed.

7. Other Uses

  • Builder pattern: the class has a private constructor that takes a builder; users must go through Builder.build().
  • Constant classes: classes holding only static final constants.
  • Controlled instance pools: classes that limit or cache the objects they hand out.
  • Constructor helpers: a private constructor called by public constructors through this(...).

8. Summary

  • A private constructor can only be called from inside its own class.
  • Use it for utility classes, singletons, static factory methods and builders.
  • Enum constructors are always private.
  • A class whose constructors are all private cannot be extended from outside.
  • Prefer enum singletons or dependency injection over hand-written singletons when possible.

Related Tutorials