Encapsulation (private, getters & setters)
Hide an object data behind private fields, then control access with getters and setters.
What you will learn
- Make fields private
- Write getter and setter methods
- Protect data with validation
Protecting your data
Encapsulation means keeping an object data safe inside the object, so outside code cannot mess it up directly. We do this by marking fields private — then they can only be touched by the class own methods.
To let other code read or change the data in a controlled way, we add small methods: getters (to read) and setters (to change).
public class BankAccount {
private double balance; // hidden from outside code
public double getBalance() { // getter: read it
return balance;
}
public void deposit(double amount) { // controlled change
if (amount > 0) {
balance = balance + amount;
}
}
}Note: Output:
(No output yet — this is the class. Because balance is private, outside code cannot set it directly. It must go through deposit, which we use next.)
Using it safely
public class Main {
public static void main(String[] args) {
BankAccount acc = new BankAccount();
acc.deposit(100);
acc.deposit(50);
acc.deposit(-9999); // ignored! amount is not > 0
System.out.println("Balance: " + acc.getBalance());
}
}Note: Output:
Balance: 150
The two valid deposits added to 150. The sneaky deposit(-9999) was ignored because the if (amount > 0) check protected the balance. This is the power of encapsulation: the object guards its own data.
Watch out: If balance were public, any code could write acc.balance = -9999; and break the account. Making it private and forcing changes through deposit stops that.
The getter / setter pattern
- Field is
private— hidden from the outside. - Getter
getX()— returns the value so others can read it. - Setter
setX(value)— changes the value, often with a check first.
Here is the classic pair in full — a getter and a validating setter that refuses bad data:
public class Person {
private int age;
public int getAge() { // getter
return age;
}
public void setAge(int newAge) { // setter with a check
if (newAge >= 0) {
age = newAge;
} else {
System.out.println("Age cannot be negative.");
}
}
}
// In main:
Person p = new Person();
p.setAge(30); // accepted
p.setAge(-5); // rejected by the check
System.out.println("Age is " + p.getAge());Note: Output:
Age cannot be negative.
Age is 30
setAge(30) passed the check and stored 30. setAge(-5) was refused, so the age stayed at 30. The getter getAge() then read it back. The private field can only ever hold a sensible value, because every change runs through the setter check.
Tip: Encapsulation lets you change how a class works inside later (for example, storing balance differently) without breaking any code that uses it — because everyone goes through your methods, not the raw fields.
Q. Why make a field private and add getters and setters?
✍️ Practice
- Add a
withdrawmethod to BankAccount that only allows the withdrawal if there is enough balance. - Make a
Personclass with a privateagefield and a setter that rejects negative ages.
🏠 Homework
- Build a
Thermostatclass with a private temperature and a setter that only accepts values between 10 and 30.