Java Encapsulation and Access Modifiers

Encapsulation means keeping the data of a class private and giving controlled access through methods. So the outside code can not put the object in a wrong state.

The problem without it

class Account {
    double balance;          // public by default in the same package: anyone can change it
}

public class Main {
    public static void main(String[] args) {
        Account a = new Account();
        a.balance = -5000;   // nonsense, but nothing stops it
        System.out.println(a.balance);
    }
}
Output

-5000.0

Private fields, public methods

class Account {
    private double balance;            // hidden

    public double getBalance() {       // getter
        return balance;
    }

    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("Amount must be positive");
        }
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount > balance) {
            throw new IllegalStateException("Not enough balance");
        }
        balance -= amount;
    }
}

public class Safe {
    public static void main(String[] args) {
        Account a = new Account();
        a.deposit(1000);
        a.withdraw(300);
        System.out.println(a.getBalance());

        try {
            a.withdraw(5000);
        } catch (IllegalStateException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}
Output

700.0
Error: Not enough balance

Now a.balance = -5000; gives a compile error, because the field is private:

class Account {
    private double balance;
}

public class Hidden {
    public static void main(String[] args) {
        Account a = new Account();
        a.balance = -5000;
    }
}
Output

Hidden.java:8: error: balance has private access in Account
a.balance = -5000;
^
1 error
error: compilation failed

Getters and setters

class Student {
    private String name;
    private int age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }
    public void setAge(int age) {
        if (age < 0 || age > 120) {
            throw new IllegalArgumentException("Invalid age: " + age);
        }
        this.age = age;
    }
}

public class GetSet {
    public static void main(String[] args) {
        Student s = new Student();
        s.setName("Riya");
        s.setAge(21);
        System.out.println(s.getName() + ", " + s.getAge());
    }
}
Output

Riya, 21

Access modifiers

ModifierSame classSame packageSubclass (other package)Everywhere
privateyesnonono
(default, no word)yesyesnono
protectedyesyesyesno
publicyesyesyesyes

Why it is good

  • Protects the data with validation.
  • You can change the inside later without breaking the code which uses the class.
  • Makes a read only field: a getter without a setter.
Note: A good rule: make fields private and open only what is really needed. In modern Java you can use a record for simple data classes. Next: Java Inheritance.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.