7.5 Encapsulation & Access Modifiers
In Object-Oriented Programming, Encapsulation refers to the bundling of data (variables) and the methods that operate on that data into a single unit (a class). Crucially, it involves restricting direct access to some of an object's components, which is why it is often referred to as Information Hiding.
Just like a medical capsule hides the bitter medicine inside but provides an easy way to swallow it safely, encapsulation hides the complex code and vulnerable data, exposing only safe "buttons" for interaction. In Java, this is achieved using Access Modifiers.
1. Types of Access Modifiers
Access modifiers are keywords used before a class, method, or variable declaration to define its scope of visibility or accessibility. They are essential for security and maintaining data integrity. Java has four levels of access modifiers (ordered from most to least accessible):
| Modifier | Accessibility Description | Visibility Scope |
|---|---|---|
public | No restrictions. Can be accessed from anywhere in the program. | Everywhere |
protected | Accessible within the same package, AND by ** subclasses acting as children**in other packages. | Package + Subclasses |
| (default) | When no modifier is specified. Accessible only within the same package. | Package only |
private | Accessible ONLY within the class where it is declared. The most restrictive scope. | Class only |
Best Practice Tip: It is a strong industry standard to declare almost all instance variables (class state) as
privateto prevent direct external manipulation.
2. Implementing Encapsulation - Getters and Setters
If all data is marked private, how can other classes read or modify that data? The answer is to provide controlled, indirect access through methods declared as public. We call these methods Getters and Setters.
public class Person {
// 1. Completely hide all variables
private String name;
private int age;
// 2. Setter method for setting value (called from outside to update data)
public void setAge(int age) {
// We can add validation logic here!
if (age < 0 || age > 150) {
System.out.println("Error: Invalid age provided.");
return;
}
this.age = age;
}
// 3. Getter method for retrieving value (called from outside to read data)
public int getAge() {
return this.age;
}
// Setter
public void setName(String name) {
this.name = name;
}
// Getter
public String getName() {
return this.name;
}
}
public class EncapsulationExample {
public static void main(String[] args) {
Person p = new Person();
// p.age = -50; // COMPILER ERROR! Cannot access private field directly.
p.setAge(-50); // Using setter: Prints "Error: Invalid age provided."
p.setAge(25); // Valid data is stored successfully.
System.out.println("The person's age is: " + p.getAge());
}
}
Why Use Getters and Setters?
- Data Integrity (Validation): As shown with the
ageexample, you can prevent invalid data (like-50or conceptually impossible values) from polluting the object's state usingifconditions within the setter. - Creating Read-Only Properties: By providing only a
Getterand removing theSetter, you can make a variable completely ** read-only**to the outside world. - Hiding Internal Implementation: The outside world simply calls the public methods. If, in the future, the internal formula for calculating an age changes, the main program interacting with
Personwon't break. This promotes excellent maintainability.
Conclusion
We have now covered the four foundational pillars of Object-Oriented Programming (OOP): Inheritance, Polymorphism, Abstraction, and Encapsulation. While these concepts might initially feel theoretical or abstract, mastering them is an absolute prerequisite for advancing into Design Patterns and robust frameworks like Spring Boot in your Java journey.