Private Constructor in Java: Introduction
By Rohan Vats
Updated on Nov 20, 2024 | 13 min read | 58.3k views
Share:
For working professionals
For fresh graduates
More
By Rohan Vats
Updated on Nov 20, 2024 | 13 min read | 58.3k views
Share:
Table of Contents
In Java, constructors are special methods used to initialize objects of a class. Like methods, constructors can also have access specifiers such as public, protected, default, and private. A private constructor is a constructor that is accessible only within the class it is defined in.
Can a constructor be private?
Yes, a constructor can be private. When declared private, it restricts the instantiation of the class to within the class itself. This means that no object of the class can be created directly from outside the class.
Let’s take a closer look at the rules, use cases, and practical examples to understand how private constructors work in Java.
Check out our free courses to get an edge over the competition.
A private constructor is a special type of constructor in Java that restricts the creation of objects from outside the class. It is often used to control how and when objects of a class are created or to prevent object creation altogether in certain cases.
Create a utility class that provides static methods for mathematical operations like addition and subtraction. Ensure no objects of the utility class can be created.
java
// Utility class for mathematical operations
class MathUtils {
// Private constructor to prevent object creation
private MathUtils() {
throw new UnsupportedOperationException("Cannot instantiate MathUtils");
}
// Static method for addition
public static int add(int a, int b) {
return a + b;
}
// Static method for subtraction
public static int subtract(int a, int b) {
return a - b;
}
}
public class Main {
public static void main(String[] args) {
// Accessing static methods without creating an object
int sum = MathUtils.add(7, 3);
int difference = MathUtils.subtract(10, 4);
// Output the results
System.out.println("Sum: " + sum);
System.out.println("Difference: " + difference);
// Uncomment the following code to see the error
// MathUtils utils = new MathUtils();
}
}
Sum: 10
Difference: 6
Copy the code into a Java IDE or text editor.
Save the file as Main.java (or use the appropriate class name if you change it).
Compile the file using javac Main.java.
Run the program using java Main.
Private constructors in Java are needed to control object creation, promote encapsulation, and support specific design patterns. They allow developers to restrict how and when a class is instantiated, which makes them a significant tool in organized and efficient coding practices.
For instance, they help maintain the integrity of Singleton classes or prevent the creation of objects for utility classes that only provide static methods. This enhances code reliability and ensures adherence to best practices in Java development.
Check out all the Trending Java Tutorial Topics in 2024.
Private constructors in Java are powerful tools for controlling how and when a class is instantiated. They follow specific rules to ensure restricted access and proper use in certain scenarios like design patterns and utility classes.
The Singleton pattern ensures that a class has only one instance throughout the application. It is particularly useful for managing shared resources like database connections, configuration settings, or logging.
A private constructor ensures that no external class can create additional instances. Instead, a static method is provided to return the sole instance. The class also typically includes lazy or eager initialization to ensure efficient resource use.
Code:
Create a Logger class to handle logging throughout the application, ensuring only one instance exists for centralized logging.
java
// Singleton Logger class implementation
class Logger {
private static Logger instance;
// Private constructor to prevent direct instantiation
private Logger() {
System.out.println("Logger Instance Created");
}
// Static method to return the single instance
public static Logger getInstance() {
if (instance == null) {
instance = new Logger();
}
return instance;
}
// Method to log messages
public void log(String message) {
System.out.println("Log: " + message);
}
}
public class Main {
public static void main(String[] args) {
// Accessing the Singleton Logger instance
Logger logger1 = Logger.getInstance();
Logger logger2 = Logger.getInstance();
// Logging messages
logger1.log("Starting the application...");
logger2.log("Loading resources...");
// Verifying that both references point to the same instance
System.out.println(logger1 == logger2); // true
}
}
Logger Instance Created
Log: Starting the application...
Log: Loading resources...
true
Utility classes provide reusable static methods or constants (e.g., Math, Collections). These classes do not require instantiation. A private constructor enforces this by preventing object creation, signaling that the class is purely functional.
Code:
Problem Statement:
Create a utility class to provide mathematical operations without allowing object instantiation.
java
// Utility class with static methods
class MathUtils {
// Private constructor to prevent instantiation
private MathUtils() {
throw new UnsupportedOperationException("Cannot instantiate MathUtils");
}
public static int add(int a, int b) {
return a + b;
}
public static int subtract(int a, int b) {
return a - b;
}
}
public class Main {
public static void main(String[] args) {
// Using static methods directly
System.out.println("Sum: " + MathUtils.add(5, 3));
System.out.println("Difference: " + MathUtils.subtract(10, 4));
// Uncommenting this line will cause a compile-time error
// MathUtils utils = new MathUtils();
}
}
Output:
Sum: 8
Difference: 6
Explanation:
The private constructor prevents object creation. Attempting to instantiate the class results in an exception, while static methods remain accessible.
Our learners also read: Free Java course!
In the Factory Method pattern, object creation is controlled via factory methods, which return instances of a class. The constructor is private to restrict direct instantiation. This allows flexibility in modifying object creation logic without changing external code.
Code:
Problem Statement:
Implement a factory method for creating products with predefined configurations.
java
class Product {
private String name;
// Private constructor to restrict object creation
private Product(String name) {
this.name = name;
}
// Factory methods
public static Product createLaptop() {
return new Product("Laptop");
}
public static Product createPhone() {
return new Product("Phone");
}
public String getName() {
return name;
}
}
public class Main {
public static void main(String[] args) {
// Creating objects using factory methods
Product laptop = Product.createLaptop();
Product phone = Product.createPhone();
System.out.println("Product 1: " + laptop.getName());
System.out.println("Product 2: " + phone.getName());
}
}
Output:
Product 1: Laptop
Product 2: Phone
Explanation:
The factory methods (createLaptop, createPhone) control how objects are created, and external classes cannot directly instantiate the Product class.
A private constructor prevents inheritance by ensuring that no subclass can call the parent class constructor. This is useful for creating immutable classes or enforcing specific behaviors in the class hierarchy.
Code:
Problem Statement:
Create a class that cannot be subclassed to ensure immutability.
java
final class ImmutableClass {
private ImmutableClass() {
System.out.println("This class cannot be subclassed");
}
public static ImmutableClass createInstance() {
return new ImmutableClass();
}
}
// Uncommenting this will cause a compile-time error
// class SubClass extends ImmutableClass {}
public class Main {
public static void main(String[] args) {
ImmutableClass obj = ImmutableClass.createInstance();
}
}
Output:
This class cannot be subclassed
Explanation:
The private constructor ensures that no other class can extend ImmutableClass, preserving its immutability and behavior.
Classes meant for storing constants or grouping static methods do not need instances. A private constructor prevents unnecessary instantiation, making the class clear in its intent.
Code:
Problem Statement:
Create a class to store application-wide constants without allowing object creation.
java
class AppConstants {
// Private constructor to prevent instantiation
private AppConstants() {
throw new UnsupportedOperationException("Cannot instantiate AppConstants");
}
public static final String APP_NAME = "MyApplication";
public static final int VERSION = 1;
}
public class Main {
public static void main(String[] args) {
System.out.println("App Name: " + AppConstants.APP_NAME);
System.out.println("Version: " + AppConstants.VERSION);
}
}
Output:
App Name: MyApplication
Version: 1
Explanation:
The private constructor ensures that the class serves its intended purpose of storing constants and cannot be instantiated.
A Singleton class ensures that only one instance of the class exists throughout the application. This is achieved using a private constructor to prevent external instantiation and a static method to provide controlled access to the instance.
Here’s a step-by-step guide to implementing a Singleton class in Java.
Create a Singleton class to manage configuration settings in an application. Ensure that only one instance exists and demonstrate its behavior.
java
// Singleton class implementation
class ConfigManager {
// Step 1: Static variable to hold the single instance
private static ConfigManager instance;
public int value; // Example variable to demonstrate instance sharing
// Step 2: Private constructor to restrict instantiation
private ConfigManager() {
System.out.println("ConfigManager Instance Created");
value = 0;
}
// Step 3: Public static method to provide access to the instance
public static ConfigManager getInstance() {
if (instance == null) {
instance = new ConfigManager();
}
return instance;
}
}
public class Main {
public static void main(String[] args) {
// Accessing the Singleton instance
ConfigManager config1 = ConfigManager.getInstance();
ConfigManager config2 = ConfigManager.getInstance();
// Modifying a shared variable using one reference
config1.value += 42;
// Verifying that the second reference points to the same instance
System.out.println("Value from config1: " + config1.value);
System.out.println("Value from config2: " + config2.value);
}
}
ConfigManager Instance Created
Value from config1: 42
Value from config2: 42
Shared State:
Changes made to the value variable using config1 are reflected in config2, proving that both references point to the same instance.
upGrad’s Exclusive Software and Tech Webinar for you –
SAAS Business – What is So Different?
Utility classes are designed to hold only static methods or constants. These classes are not meant to be instantiated. Using a private constructor ensures no one can create an object of the class, keeping it functional and straightforward.
Create a StringUtils class with static methods to reverse a string and check if a string is a palindrome. Ensure no one can create an object of this class.
Code:
java
// Utility class for text operations
public class StringUtils {
// Private constructor to block instantiation
private StringUtils() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
// Static method to reverse a string
public static String reverse(String input) {
if (input == null) {
return null;
}
return new StringBuilder(input).reverse().toString();
}
// Static method to check if a string is a palindrome
public static boolean isPalindrome(String input) {
if (input == null) {
return false;
}
String reversed = reverse(input);
return input.equalsIgnoreCase(reversed);
}
}
public class Main {
public static void main(String[] args) {
// Using static methods directly
String text = "Level";
System.out.println("Original: " + text);
System.out.println("Reversed: " + StringUtils.reverse(text));
System.out.println("Is Palindrome: " + StringUtils.isPalindrome(text));
// Uncommenting this line will cause an exception
// StringUtils utils = new StringUtils();
}
}
Original: Level
Reversed: leveL
Is Palindrome: true
The Builder pattern helps create complex objects step by step. Using a private constructor in the main class ensures that only the Builder class is responsible for creating objects. This approach avoids creating multiple constructors and keeps the code simple and clear.
Create an Employee class with fields like name, age, and department. Use the Builder pattern to allow flexible object creation.
Code:
java
public class Employee {
// Fields of the Employee class
private final String name;
private final int age;
private final String department;
// Step 1: Private constructor to restrict direct instantiation
private Employee(String name, int age, String department) {
this.name = name;
this.age = age;
this.department = department;
}
// Step 2: Inner Builder class to manage object creation
public static class Builder {
private String name;
private int age;
private String department;
// Step 3: Setter methods for each field
public Builder setName(String name) {
this.name = name;
return this; // Enable method chaining
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setDepartment(String department) {
this.department = department;
return this;
}
// Step 4: Build method to create the Employee object
public Employee build() {
return new Employee(name, age, department);
}
}
// Method to display Employee details
@Override
public String toString() {
return "Employee{name='" + name + "', age=" + age + ", department='" + department + "'}";
}
// Main method to demonstrate the Builder Pattern
public static void main(String[] args) {
// Step 5: Using the Builder class to create an Employee object
Employee employee = new Employee.Builder()
.setName("John Doe")
.setAge(30)
.setDepartment("Software Development")
.build();
System.out.println(employee);
// Creating another Employee with partial fields
Employee anotherEmployee = new Employee.Builder()
.setName("Jane Smith")
.setDepartment("HR")
.build();
System.out.println(anotherEmployee);
}
}
Employee{name='John Doe', age=30, department='Software Development'}
Employee{name='Jane Smith', age=0, department='HR'}
Studying software development online is a practical choice today. Online learning offers flexibility, making it easier to balance work, life, and education. As the demand for tech professionals grows, having strong programming skills is more important than ever.
With online courses, you can gain valuable skills without disrupting your routine.
upGrad’s Software Development courses are designed for learners of all levels. They provide practical knowledge and industry-recognized certifications to help you grow in your career.
Start Your Journey with upGrad
Stay ahead in the tech industry with upGrad's online programs.
Learn Software Development Online from Top Universities
Earn an Executive PG Program, Advanced Certificate, or Master’s Degree in software development. Gain industry-relevant skills and fast-track your career today!
Enhance your expertise with our Software Development Free Courses. Explore the programs below to find your perfect fit.
Advance your in-demand software development skills with our top programs. Discover the right course for you below.
Get Free Consultation
By submitting, I accept the T&C and
Privacy Policy
India’s #1 Tech University
Executive PG Certification in AI-Powered Full Stack Development
77%
seats filled
Top Resources