Private Constructors

Naveen AnamaneniUpdated · 5 min read

A railway station has exactly one station master's office; you can't open a second one by walking in and asking. Some classes need that kind of control over how their objects are made, or whether they're made at all. Marking a constructor private means only code inside the class can call it. Other code can't write new, and the class decides how objects come into existence.

Three Reasons to Make a Constructor Private

new is blocked outside; the class controls creation
UseExample from Java itselfIdea
Utility classjava.lang.Math, java.util.ArraysOnly static methods; objects make no sense
Static factory methodsList.of(...), LocalDate.of(...)Creation goes through named methods that can check, cache or choose
SingletonA single configuration or registry objectExactly one object for the whole program

A Utility Class

Gst.java▶ Try it
public class Gst {
    static class GstUtil {
        private GstUtil() {}
 
        static long tax(long amount, int ratePercent) {
            return amount * ratePercent / 100;
        }
    }
 
    public static void main(String[] args) {
        System.out.println("GST on Rs. 2000: Rs. " + GstUtil.tax(2000, 18));
    }
}
Output
GST on Rs. 2000: Rs. 360

Line 3 makes the constructor private, so new GstUtil() from another class fails:

Compiler output
Priv.java:2: error: Util() has private access in Util
public class Priv { public static void main(String[] a) { new Util(); } }
                                                          ^

Factory Methods with Rules

Fares.java▶ Try it
public class Fares {
    static class Fare {
        final int km;
 
        private Fare(int km) {
            this.km = km;
        }
 
        static Fare of(int km) {
            if (km <= 0) {
                throw new IllegalArgumentException("Distance must be positive");
            }
            return new Fare(km);
        }
 
        int rupees() { return km * 2; }
    }
 
    public static void main(String[] args) {
        System.out.println("300 km: Rs. " + Fare.of(300).rupees());
    }
}
Output
300 km: Rs. 600

Outside code can only use Fare.of(...), so every Fare goes through the check. The name of also reads better than a bare new.

A Singleton

Config.java▶ Try it
public class Config {
    static class AppConfig {
        private static final AppConfig INSTANCE = new AppConfig();
        final String currency = "INR";
 
        private AppConfig() {}
 
        static AppConfig getInstance() { return INSTANCE; }
    }
 
    public static void main(String[] args) {
        AppConfig a = AppConfig.getInstance();
        AppConfig b = AppConfig.getInstance();
        System.out.println(a.currency + ", same object: " + (a == b));
    }
}
Output
INR, same object: true

How it works

  1. Line 3 creates the only AppConfig object when the class is loaded, and keeps it in a static final field.
  2. Line 6: the private constructor stops anyone else from making another.
  3. Line 8: everyone gets the same object through getInstance(), as a == b shows.

Try it yourself: add a counter to the private constructor and call getInstance() five times. How many times does the constructor run?

Common Mistakes

Forgetting the private constructor on a utility class. The compiler adds a public one, and new GstUtil() becomes possible.

Thinking private stops all creation. Reflection can still call a private constructor; serialization and cloning also create objects. Singletons that must be bulletproof use an enum.

Making a constructor private but no factory method. Then nobody, not even you, can get an object.

Interview Corner

What is the use of a private constructor?

It stops other classes from creating objects with new. It's used for utility classes that only have static methods (like Math), for classes that create objects only through static factory methods, and for singletons that must have exactly one instance.

How do you create a singleton class in Java?

Make the constructor private, keep the single instance in a private static final field, and return it from a static getInstance() method. The simplest robust form is an enum with one constant, which also handles serialization and reflection correctly.

Practice

  1. Easy: Write a utility class Temp with a private constructor and static methods cToF and fToC.
  2. Harder: Write a class PinCode with a private constructor and a factory method of(String digits) that accepts only exactly six digits.

Quick check: Private constructors

4 questions
1Who can call a private constructor?
2Why does java.lang.Math have a private constructor?
3In a singleton, how many objects of the class exist?
4What is a static factory method?

Key Takeaways

Was this tutorial helpful?

Lesson 101 of 482