Java Encapsulation
Encapsulation means keeping an object's data private and letting other code change it only through the object's own methods. The object becomes responsible for its data: it can check every change, refuse bad values and keep everything consistent. It is one of the main ideas of object-oriented programming, and it builds directly on the private modifier from Modifiers.
Getters and setters
The usual pattern is: private fields, a public getter to read each one, and a public setter to change it where changing makes sense. By convention they are named getX and setX (and isX for booleans):
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
setAge(age);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0 || age > 150) {
System.out.println("Ignored impossible age: " + age);
return;
}
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person("Kavya", 28);
p.setAge(29);
p.setAge(-4);
System.out.println(p.getName() + " is " + p.getAge());
}
}Ignored impossible age: -4 Kavya is 29
The constructor also uses setAge, so the same check protects new objects. A program can no longer create a person aged -4 by accident.
Read-only data
If a field has a getter but no setter, other classes can read it but never change it. Combined with final this makes data that is fixed once the object exists:
class Order {
private final String id;
private int quantity;
public Order(String id, int quantity) {
this.id = id;
this.quantity = quantity;
}
public String getId() {
return id;
}
public int getQuantity() {
return quantity;
}
public void addOne() {
quantity++;
}
}
public class Main {
public static void main(String[] args) {
Order o = new Order("A-17", 2);
o.addOne();
System.out.println(o.getId() + ": " + o.getQuantity() + " items");
}
}A-17: 3 items
The quantity can only grow through addOne, and the ID cannot change at all.
Keeping data consistent
Encapsulation shines when fields depend on each other. Here the class keeps the total of all marks in step with the number of marks, so average is always right:
class Marks {
private int count;
private int total;
public void add(int mark) {
if (mark >= 0 && mark <= 100) {
count++;
total += mark;
}
}
public double average() {
return count == 0 ? 0 : (double) total / count;
}
}
public class Main {
public static void main(String[] args) {
Marks m = new Marks();
m.add(80);
m.add(90);
m.add(250);
m.add(70);
System.out.println("Average: " + m.average());
}
}Average: 80.0
If other code could change count or total directly, the average could become wrong. Because both are private, add is the only way in, and it changes them together.
Why it matters
- Safety: bad values are refused in one place.
- Freedom to change: the class can store its data differently later (for example in paise instead of rupees) without breaking the code that uses it, because that code only calls the methods.
- Clarity: the public methods describe what an object can do; the details stay hidden.
The Records topic shows a short way to write simple classes whose data never changes.
Practice exercises
- Write a class
Temperaturewith a privatecelsiusfield, a getter, and a setter that refuses values below -273.15. - Add a getter
getFahrenheit()that is calculated fromcelsiusinstead of stored. - Write a class
Counterwhose value can only be increased byincrement()and read bygetValue().