Access Modifiers in Java
Access modifiers in Java control who can see and use your classes, fields, methods, and
constructors. There are four levels: private, default, protected, and
public. Using them well is how you stop other code from breaking your objects.
What are access modifiers in Java?
An access modifier is a keyword you put in front of a declaration to set its visibility. Think of an office building: some rooms are open to the public, some only to staff, and some only to one person with the key.
Why not just make everything public?
Because then any code anywhere can change your object's data, including setting a bank balance to a nonsense value. Hiding details means fewer bugs, and you can change your class's internals later without breaking everyone who uses it.
Java access modifiers table: who can see what?
This table shows each modifier's visibility. Read across a row to see where that modifier lets code reach:
| Modifier | Same class | Same package | Subclass (other package) | Everywhere else |
|---|---|---|---|---|
private | ✔ Yes | ✘ No | ✘ No | ✘ No |
| default (none) | ✔ Yes | ✔ Yes | ✘ No | ✘ No |
protected | ✔ Yes | ✔ Yes | ✔ Yes | ✘ No |
public | ✔ Yes | ✔ Yes | ✔ Yes | ✔ Yes |
Notice the pattern: each level down the table opens one more "door".
Explore each access modifier
private
Visible only inside the same class. The strictest level.
- ✔ Same class
- ✘ Same package
- ✘ Subclass in another package
- ✘ Any other code
- Best for: fields and internal helper methods.
private double balance; (default)
No keyword at all. Visible to every class in the same package. Also called package-private.
- ✔ Same class
- ✔ Same package
- ✘ Subclass in another package
- ✘ Any other code
- Best for: classes that are internal details of one package.
double balance; // no modifier protected
Visible in the same package, plus subclasses in other packages.
- ✔ Same class
- ✔ Same package
- ✔ Subclass in another package (through inheritance)
- ✘ Any other code
- Best for: hooks you deliberately let subclasses use or override.
protected void onDeposit(double amount) { } public
Visible everywhere. The most open level.
- ✔ Same class
- ✔ Same package
- ✔ Subclass in another package
- ✔ Any other code
- Best for: the methods other code is meant to call, your class's "API".
public void deposit(double amount) { } The private modifier
private members can only be used by code inside the same class. This is the right default for
fields. Other classes then have to go through your methods, where you can check the values:
public class BankAccount {
private double balance; // nobody outside can touch this directly
public void deposit(double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Deposit must be positive");
}
balance += amount;
}
public double getBalance() { // read-only access from outside
return balance;
}
} BankAccount acc = new BankAccount();
acc.deposit(100);
System.out.println(acc.getBalance()); // 100.0
acc.balance = -5000; // ✘ compile error: balance has private access This pattern, with private fields and public methods that guard them, is called encapsulation. It's one of the most important habits in Java.
The default (package-private) modifier
If you write no modifier, the member is visible to every class in the same package.
A package is a folder-like group of related classes, declared with package com.example.bank; at the
top of a file.
package com.example.bank;
class InterestCalculator { // only classes in com.example.bank can use this
double monthlyRate(double yearlyRate) {
return yearlyRate / 12;
}
} Watch out: "default" access has nothing to do with the default keyword used in switch statements or interface default methods. It just means "no modifier written".
The protected modifier
protected is like default access, plus one extra door: subclasses in other packages
can use it through inheritance.
package com.example.bank;
public class Account {
protected double balance;
}
// ---- different file, different package ----
package com.example.savings;
import com.example.bank.Account;
public class SavingsAccount extends Account {
public void addInterest(double rate) {
balance += balance * rate; // ✔ allowed: SavingsAccount inherits balance
}
} Should I use protected for fields?
Usually not. A protected field lets every subclass change it without checks. A safer pattern is a private field plus a protected method that subclasses can call.
The public modifier
public means any code can use it. Make public only what other classes are meant to call.
That's your class's API (its public "menu"). Everything else should stay hidden.
Modules (Java 9+): in a project that uses Java modules, a public class is only visible to other modules if its package is exported in module-info.java. Most beginner projects don't use modules, so public simply means "everywhere".
Where can each modifier be used?
| Applies to | Allowed modifiers |
|---|---|
| Top-level class or interface | public or default only |
| Fields, methods, constructors | All four |
| Nested (inner) classes | All four |
| Interface methods | public (implied if omitted) or private (Java 9+) |
| Local variables inside a method | None. They're already visible only inside that method. |
How do you choose the right access modifier?
A simple rule of thumb that professional Java developers follow:
- Make fields
private, almost always. - Make methods
publiconly if other classes need to call them. - Use default for helper classes that belong to one package.
- Use
protectedonly when you're deliberately designing for subclasses.
Tip: it's easy to make something more visible later, but making it less visible can break other people's code. Start strict.
Quick recap
private: same class only. default: same package.protected: package + subclasses.public: everywhere.- Top-level classes can only be
publicor default. - Private fields + public methods = encapsulation.
- An overriding method can't be more restrictive than the method it overrides.
What's next?
You've seen protected work with subclasses. Now learn how subclasses work in
inheritance in Java, or review
classes and objects.
Frequently Asked Questions
What is the default access modifier in Java?
If you write no modifier, Java uses 'package-private' access, often called default. The class, field, or method is visible to code in the same package only. There is no keyword for it, so you simply leave the modifier out.
What is the difference between private and protected in Java?
Private members are visible only inside the class that declares them. Protected members are visible to every class in the same package and also to subclasses in other packages. Use private by default and protected only when subclasses genuinely need access.
Can a top-level class be private in Java?
No. A top-level class can only be public or package-private (no modifier). Private and protected are allowed only on members, including nested classes declared inside another class.
Why should fields be private?
Private fields force other code to go through your methods, so you can validate changes and keep the object in a valid state. It also lets you change how data is stored later without breaking code that uses your class. This idea is called encapsulation.
Can an overriding method have a more restrictive access modifier?
No. When you override a method, you can keep the same access level or make it more open, but never more restrictive. For example, a public method in a parent class must stay public in the child class, or the code won't compile.