Access Modifiers in Java
In an office, some rooms are open to visitors, some only to staff, some only to one team, and a locker is for its owner alone. Java has the same four levels for code. An access modifier on a class, field, method or constructor decides who may use it: only its own class (private), its package (no modifier), its package plus subclasses (protected), or everyone (public).
The Four Levels
| Modifier | Same class | Same package | Subclass in another package | Everywhere |
|---|---|---|---|---|
private | Yes | No | No | No |
| (none), package-private | Yes | Yes | No | No |
protected | Yes | Yes | Yes, through inheritance | No |
public | Yes | Yes | Yes | Yes |
In a Real Project
The bank project from this chapter has three packages. Account lives in com.poolstring.bank.model and uses all four levels:
package com.poolstring.bank.model;
public class Account {
private final String holder;
private long balance;
public Account(String holder, long opening) {
this.holder = holder;
this.balance = opening;
}
public String getHolder() { return holder; }
public long getBalance() { return balance; }
void adjust(long amount) { balance += amount; }
protected void audit(String note) {
System.out.println("[audit] " + holder + ": " + note);
}
public boolean withdraw(long amount) {
if (amount <= 0 || amount > balance) {
return false;
}
adjust(-amount);
audit("withdraw " + amount);
return true;
}
public void deposit(long amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Deposit must be positive");
}
adjust(amount);
audit("deposit " + amount);
}
}| Member | Level | Why |
|---|---|---|
holder, balance | private | Only Account's own methods may change them |
adjust | package-private | A low-level helper for classes in the model package only |
audit | protected | Subclasses such as a premium account may add audit lines |
Constructor, getters, deposit, withdraw | public | The API the rest of the program uses |
A class in another package, com.poolstring.bank.app, tries each one:
package com.poolstring.bank.app;
import com.poolstring.bank.model.Account;
public class Peek {
public static void main(String[] args) {
Account a = new Account("Srihitha", 500);
a.balance = 1000000;
a.adjust(50);
a.audit("peek");
}
}javac -cp out -d out src/com/poolstring/bank/app/Peek.javasrc/com/poolstring/bank/app/Peek.java:8: error: balance has private access in Account
a.balance = 1000000;
^
src/com/poolstring/bank/app/Peek.java:9: error: adjust(long) is not public in Account; cannot be accessed from outside package
a.adjust(50);
^
src/com/poolstring/bank/app/Peek.java:10: error: audit(String) has protected access in Account
a.audit("peek");
^
3 errorsThe compiler enforces all three levels: private, package-private and protected are all closed to an unrelated class in another package.
The protected Rule
protected opens a member to subclasses in other packages, but only through inheritance: a subclass may call it on itself (or on objects of its own type), not on any Account it happens to hold:
package com.poolstring.bank.app;
import com.poolstring.bank.model.Account;
public class PremiumAccount extends Account {
public PremiumAccount(String holder, long opening) {
super(holder, opening);
}
public void review(Account other) {
audit("premium review");
other.audit("not allowed");
}
}src/com/poolstring/bank/app/PremiumAccount.java:12: error: audit(String) has protected access in Account
other.audit("not allowed");
^
1 errorLine 11, audit(...) on itself, compiles. Line 12, on another Account, doesn't.
Modifiers on Classes
| Where | Allowed modifiers |
|---|---|
| Top-level class or interface | public or none (package-private) |
| Nested class, field, method, constructor | All four |
| Interface members | public by default; private allowed for helper methods |
A file can contain at most one public top-level class, and the file must be named after it:
Shop.java:1: error: class Cart is public, should be declared in a file named Cart.java
public class Cart { }
^
1 errorCommon Mistakes
Making everything public. Every public member is a promise you must keep; start private.
Expecting protected to hide from the package. Classes in the same package can use protected members freely.
Forgetting that package-private is the default. A method without a modifier isn't public; code in other packages can't call it.
Interview Corner
What are the access modifiers in Java?
There are four levels. private allows access only within the same class. Package-private, the default with no keyword, allows access within the same package. protected allows access within the package and from subclasses in other packages through inheritance. public allows access from everywhere. Top-level classes can only be public or package-private.
Can a subclass in another package call a protected method on a parent-type object?
Not on an arbitrary parent-type object. Outside the package, a subclass can access a protected member only through references of its own type or a subtype, such as this.audit(). Calling other.audit() on a plain Account reference is a compile error.
Practice
- Easy: For each member of
Account, say whetherTransferServiceincom.poolstring.bank.servicecan use it. - Harder: Move
Peekinto themodelpackage (change itspackageline and folder). Which of the three errors disappear, and why?
Key Takeaways
Was this tutorial helpful?