Public, protected, private, and package-private in Java: A Complete Breakdown

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What Do Access Modifiers in Java Hide? A Deep Dive into Encapsulation

\n\n

Everyone who starts learning Java encounters the mysterious words public, private, and protected before fields and methods. But what do they actually mean? Why can't you just make everything public and live in peace? And what is this mysterious package-private that most tutorials are silent about?

\n\n

In this article, we will break down the difference between public, protected, package-private, and private in Java using real code examples. You will learn how each modifier works, in which situations to apply them, and why choosing the right access modifier is a sign of good architectural thinking. Let's go!

\n\n

Why Are Access Modifiers Even Needed?

\n\n

Imagine you are building a house. You have a front door (accessible to everyone), a guest room (accessible to friends), a private study (only for family), and a safe (only for you). Access modifiers in Java work exactly the same way: they determine who can "enter" your class, method, or field.

\n\n

The main goal is encapsulation. We hide the internal implementation details of a class and only expose what is truly needed to the outside. This protects data from accidental modification and simplifies code maintenance.

\n\n

A Quick Overview of the Four Access Levels

\n\n

In Java, there are four access levels (from most restrictive to most open):

\n\n
    \n
  • private — access only within the class
  • \n
  • package-private (default) — access within the class and package
  • \n
  • protected — class + package + subclasses
  • \n
  • public — access from everywhere
  • \n
\n\n

Private: "Mine and No One Else's"

\n\n

The private modifier is the most restrictive. A field or method marked as private is accessible only within the same class. Neither subclasses nor classes from the same package can access it.

\n\n
public class BankAccount {\n    private double balance;  // Accessible only within the class\n\n    public BankAccount(double initialBalance) {\n        this.balance = initialBalance;\n    }\n\n    public void deposit(double amount) {\n        if (amount > 0) {\n            balance += amount;\n        }\n    }\n\n    // This method can see the private field because it is inside the class\n    public double getBalance() {\n        return balance;\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        BankAccount account = new BankAccount(1000);\n        // account.balance = 5000;  // Compilation error! balance is private\n        System.out.println(account.getBalance());  // Works via a public method\n    }\n}
\n\n

When to use: for internal class data that should not be changed from outside (e.g., a counter, an object's internal state).

\n\n

Package-private (default): "The Quiet Neighbor"

\n\n

If you do not specify any modifier, Java automatically makes the access package-private. This means the field or method is visible to all classes within the same package, but not visible outside of it.

\n\n
package com.pythonlib.utils;\n\nclass Helper {  // package-private class (no modifier)\n    String secretMessage = "Visible only within the package";  // package-private field\n\n    void displayMessage() {  // package-private method\n        System.out.println(secretMessage);\n    }\n}\n\npackage com.pythonlib.app;\n\nimport com.pythonlib.utils.Helper;\n\npublic class App {\n    public static void main(String[] args) {\n        Helper helper = new Helper();\n        // helper.secretMessage = "Error!";  // Not visible — different package\n        // helper.displayMessage();  // Compilation error\n    }\n}
\n\n

When to use: for utility classes

Blogs

Book Recommendations