Access Modifiers
public, private, protected, default
Interview Relevant: Scope and visibility questions
6 min read
Access Modifiers in Java
Access modifiers control the visibility and accessibility of classes, methods, and fields. Java has four levels of access.
Access Levels (Most to Least Restrictive)
| Modifier | Class | Package | Subclass | World |
|---|---|---|---|---|
private |
✅ | ❌ | ❌ | ❌ |
| (default) | ✅ | ✅ | ❌ | ❌ |
protected |
✅ | ✅ | ✅ | ❌ |
public |
✅ | ✅ | ✅ | ✅ |
🔑 Best Practice: Start with most restrictive (private) and only increase access as needed. This is the principle of least privilege.
💡 Note: Top-level classes can only be public or default. private and protected are only for members.
Code Examples
private modifier - most restrictive
java
1// private - Only accessible within the same class
2public class BankAccount {
3 private double balance; // Only this class can access
4 private String accountNumber;
5
6 public BankAccount(String accountNumber) {
7 this.accountNumber = accountNumber;
8 this.balance = 0;
9 }
10
11 // Private helper method
12 private boolean isValidAmount(double amount) {
13 return amount > 0;
14 }
15
16 public void deposit(double amount) {
17 if (isValidAmount(amount)) { // Can call private method
18 balance += amount; // Can access private field
19 }
20 }
21
22 public double getBalance() {
23 return balance; // Controlled access via getter
24 }
25}
26
27// Outside the class:
28BankAccount acc = new BankAccount("123");
29// acc.balance = 1000000; // ERROR! private
30// acc.isValidAmount(100); // ERROR! private
31acc.deposit(100); // OK - public method
32acc.getBalance(); // OK - public methoddefault (package-private) access
java
1// default (package-private) - No modifier keyword
2// File: com/myapp/User.java
3package com.myapp;
4
5class User { // default class - package access only
6 String name; // default field
7 int age;
8
9 void display() { // default method
10 System.out.println(name + ", " + age);
11 }
12}
13
14// File: com/myapp/UserManager.java
15package com.myapp;
16
17public class UserManager {
18 public void createUser() {
19 User user = new User(); // OK - same package
20 user.name = "Alice"; // OK - same package
21 user.display(); // OK - same package
22 }
23}
24
25// File: com/other/External.java
26package com.other;
27import com.myapp.*;
28
29public class External {
30 public void test() {
31 // User user = new User(); // ERROR! User class not visible
32 UserManager um = new UserManager(); // OK - public class
33 }
34}protected modifier for inheritance
java
1// protected - Package + Subclass access
2package com.animals;
3
4public class Animal {
5 protected String name; // Accessible in subclasses
6 protected int age;
7
8 protected void makeSound() { // Accessible in subclasses
9 System.out.println("Some sound");
10 }
11}
12
13// Same package - full access
14package com.animals;
15
16public class Zoo {
17 public void test() {
18 Animal a = new Animal();
19 a.name = "Leo"; // OK - same package
20 a.makeSound(); // OK - same package
21 }
22}
23
24// Different package, but subclass - limited access
25package com.pets;
26import com.animals.Animal;
27
28public class Dog extends Animal {
29 public void bark() {
30 name = "Buddy"; // OK - inherited protected
31 makeSound(); // OK - inherited protected
32
33 // But NOT through another instance!
34 Animal other = new Animal();
35 // other.name = "X"; // ERROR! Not via different instance
36 }
37}Complete example with all modifiers
java
1// public - Accessible from everywhere
2public class PublicAPI {
3 public static final String VERSION = "1.0";
4
5 public String publicField;
6
7 public PublicAPI() { }
8
9 public void publicMethod() {
10 System.out.println("Anyone can call this");
11 }
12}
13
14// Complete Example - Encapsulation Best Practices
15public class Employee {
16 // Private fields - hide internal state
17 private int id;
18 private String name;
19 private double salary;
20
21 // Public constructor - allow creation
22 public Employee(int id, String name) {
23 this.id = id;
24 this.name = name;
25 this.salary = 0;
26 }
27
28 // Public getters - read access
29 public int getId() { return id; }
30 public String getName() { return name; }
31 public double getSalary() { return salary; }
32
33 // Public setter with validation
34 public void setSalary(double salary) {
35 if (salary >= 0) {
36 this.salary = salary;
37 }
38 }
39
40 // Private helper - internal use only
41 private void log(String message) {
42 System.out.println("[Employee " + id + "] " + message);
43 }
44
45 // Protected method - for subclasses
46 protected void updateRecord() {
47 log("Record updated");
48 }
49}Use Cases
- Encapsulation - hiding implementation details
- API design - controlling public interface
- Inheritance - sharing with subclasses
- Package organization - related class access
- Security - protecting sensitive data
- Maintainability - limiting change impact
Common Mistakes to Avoid
- Making everything public
- Using protected when private would work
- Forgetting about default access
- Protected != subclass-only
- Exposing internal state unnecessarily
- Not understanding package boundaries