Java Private Access Modifier
Table of Contents + β
In the last lesson you learned about the Java public access modifier. public is great for methods you want everyone to call, but dangerous for data. We need a way to lock a member down so only the class itself can touch it. That tool is private. Letβs learn it.
π€ Why lock data away at all?
Here is a User class where the password field is open.
class User { String password; // β wide open, anyone can read or change it}
// somewhere far away in the program:user.password = ""; // β blanked the passwordSystem.out.println(user.password); // β printed it in plain sightNothing stops those lines. The field has no guard, so any code can read or wipe the password. Here is why that hurts in a real program:
- The wrong value can come from anywhere. A typo in some far-off file can blank a field.
- Secrets leak. A password or a balance should not be readable by every part of the program.
- Debugging gets painful. When a field is wrong, every line that touches it is a suspect.
We want the object to guard its own data and decide who gets in. That is what private is for.
π What private means
The private keyword means one thing. Only code inside the same class can use it. Everything else is locked out: subclasses, classes in the same folder, classes anywhere. Same class, yes. Anywhere else, no.
Here is the same user, now with a private field.
class User { private String password; // β
only the User class can touch this}That one keyword seals the password inside User. No outside line can read or overwrite it. This is the data-hiding idea, the core tool for encapsulation: keeping data safe behind methods.
But now there is a fresh problem. If outside code cannot touch password at all, how does anyone set it or check it? A locked box with no key is useless. That is what public getters and setters are for.
πͺ Private fields with public getters and setters
The standard pattern is short. Make the field private, then add public methods to read and change it. The methods are the only doors, and you control each one.
- A getter reads the field and returns its value.
- A setter changes the field, but it can check the new value first and reject anything bad.
Here is the user with a private password and a setter that enforces a rule.
class User { private String password;
// β
getter: read the password length, not the password itself public int getPasswordLength() { return password == null ? 0 : password.length(); }
// β
setter: change the password, but only if it is long enough public void setPassword(String newPassword) { if (newPassword != null && newPassword.length() >= 8) { password = newPassword; } else { System.out.println("Password must be at least 8 characters."); } }}Walk through what each piece does:
getPasswordLengthreturns the length, not the password text. The field is private, so you decide exactly what leaks out.setPassworddoes not blindly assign. It checks the length first, and a short or missing one is rejected with a message.- Outside code can no longer set
passwordto whatever it likes. The rule lives in one place, where it cannot be skipped.
Now run it against the class above. We try one bad password and one good one, then check the length.
public class Main { public static void main(String[] args) { User user = new User(); user.setPassword("123"); // β too short, rejected user.setPassword("supersecret"); // β
valid, accepted System.out.println("Length: " + user.getPasswordLength()); }}setPassword("123")is shorter than 8, so the setter prints a message and the field stays empty.setPassword("supersecret")is long enough, so the password is stored.getPasswordLength()returns 11.
Output
Password must be at least 8 characters.Length: 11The bad password never made it in, and the secret text was never exposed. That is the payoff of private.
π« Proof that private is locked from outside
Letβs see the compiler actually stop us. Here Main is a different class, and it tries to touch the private field directly.
public class Main { public static void main(String[] args) { User user = new User(); user.password = "hello"; // β trying to reach the private field }}
class User { private String password;}This does not compile. The mistake is caught at build time, not later when a secret leaks.
Compile error
Main.java:4: error: password has private access in User user.password = "hello"; ^1 errorNow the same idea done the right way, through the public setter.
public class Main { public static void main(String[] args) { User user = new User(); user.setPassword("hello123"); // β
goes through the public door System.out.println("Length: " + user.getPasswordLength()); }}Output
Length: 8The direct path is blocked. The controlled path works. That is private doing its job.
π§° Private helper methods
private is not only for fields. A private method is a helper that only the class itself calls. The outside world has no business using it. Here an OrderProcessor splits its work into small private helpers, with one public method as the entry point.
class OrderProcessor {
// β
the one public door public void process(double amount) { if (isValid(amount)) { double total = addTax(amount); System.out.println("Charging: " + total); } else { System.out.println("Invalid amount."); } }
// β
private helper, only used inside this class private boolean isValid(double amount) { return amount > 0; }
// β
private helper, only used inside this class private double addTax(double amount) { return amount * 1.1; }}Letβs run it.
public class Main { public static void main(String[] args) { OrderProcessor processor = new OrderProcessor(); processor.process(100); // β
valid processor.process(-5); // β invalid }}Output
Charging: 110.00000000000001Invalid amount.Why hide isValid and addTax? They are details.
- The outside world should call
processand nothing else. - If those helpers were public, other code could depend on them, and then you could never change them.
- Keeping them private leaves you free to rename, rewrite, or delete them later.
Public face, private machinery
Think of a class as a machine. The public methods are the buttons on the front. The private fields and methods are the gears inside the case. Users press buttons. They never reach into the gears. private is the case that keeps the gears out of reach.
π Private constructors, briefly
You can even make a constructor private. A constructor builds an object, so a private one means only the class itself can create instances. Outside code cannot write new .... This powers two common patterns. The first is a singleton, a class that should have exactly one object in the whole program.
class Settings { private static Settings instance;
private Settings() { } // β no one outside can call new Settings()
public static Settings getInstance() { if (instance == null) { instance = new Settings(); // β
the class makes the one object } return instance; }}The private constructor blocks new Settings() from outside. The only way in is getInstance, which always hands back the same single object.
The second is a utility class, only a bag of static helper methods that should never become an object.
class MathUtils { private MathUtils() { } // β stops anyone making a MathUtils object
public static int square(int n) { return n * n; }}You call MathUtils.square(5) without ever creating an object. The private constructor makes that intent clear and stops a pointless new MathUtils(). The takeaway: a private constructor means the class controls its own creation.
β οΈ Common Mistakes
private is easy to misuse when you are new to it.
Expecting a subclass to reach a private member. This is the big one. A subclass does not get access to the parentβs private fields or methods. private means same class only, and a subclass is a different class.
class Animal { private String name = "Rex";}
class Dog extends Animal { public void show() { // β wrong: name is private in Animal, Dog cannot see it System.out.println(name); }}If you want subclasses to reach a member, that is what protected is for, which is the next lesson. For now, just know that private shuts subclasses out too.
class Animal { private String name = "Rex";
// β
right: expose it through a method the subclass can call public String getName() { return name; }}
class Dog extends Animal { public void show() { System.out.println(getName()); // β
goes through the public method }}Making helper methods public. If an internal helper is public, outside code can start calling it and depending on it. Then you can never safely change it. Keep helpers private so you stay free to rework them.
// β wrong: an internal detail exposed to the worldpublic double addTax(double amount) { return amount * 1.1; }
// β
right: hidden, only the class uses itprivate double addTax(double amount) { return amount * 1.1; }Leaving fields package-default by accident. Writing no modifier is not the same as private. A field with no modifier is open to every class in the same folder. If you meant βonly this class,β you must type private.
// β wrong: no modifier, so the whole package can touch itdouble balance;
// β
right: truly hiddenprivate double balance;β Best Practices
Here are the habits that make private pay off.
- Make fields
privateby default. Start every field locked. Open it only through a getter or setter you added on purpose. - Keep helper methods private. If a method is only used inside the class, mark it
privateso it stays a free-to-change detail. - Expose only what is needed. Skip the setter to make a field read-only. Skip the getter if outsiders should not even see the value.
- Put validation in the setter. The setter is the one gate the data must pass. Reject bad values right there.
- Use a private constructor on purpose. Reach for it when you want a singleton or a static-only utility class, not by accident.
π§© What Youβve Learned
Nicely done. Letβs recap the private access modifier.
- β
privaterestricts a member to the same class only. Subclasses and other classes are locked out. - β It is the core tool for encapsulation, the data-hiding part.
- β The standard pattern is a private field with public getters and setters, where the setter can validate.
- β Touching a private member from another class is a compile error, caught at build time.
- β Private helper methods keep internal details hidden so you can change them freely.
- β A private constructor lets the class control its own creation, used for singletons and utility classes.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Who can access a private member?
Why: private restricts access to code inside the same class only. Even subclasses cannot reach it.
- 2
Can a subclass access a private field of its parent?
Why: A subclass is a different class, so it cannot see the parent's private members. Use protected for that.
- 3
What happens if you read a private field from another class?
Why: The code does not compile. The build fails with a 'has private access' error before the program runs.
- 4
What is a private constructor used for?
Why: A private constructor stops outside code from using new, which powers singletons and static-only utility classes.
π Whatβs Next?
private locks a member to one class, even shutting out subclasses. But sometimes you do want subclasses to inherit and use a member, while still hiding it from unrelated code. There is a modifier built for exactly that middle ground. Letβs learn it.