Encapsulation in Java
In this article, we will explore the concept of encapsulation in the Java programming language. We will first discuss data hiding or abstraction, the need for encapsulation, and its advantages.
We will examine various examples of programs that utilise encapsulation. To grasp the concept more quickly and master it effectively, I suggest practising each code snippet in the article, making modifications, and experimenting with the code to cover various scenarios. This will help you better understand the code and learn how to apply it in multiple situations.
What do you mean by object encapsulation?
In the IT world, encapsulation is one of the eight fundamental pillars of the Object-Oriented Paradigm. It stores a class’s data members and data methods together, bundling the fields and methods inside a single class.
Encapsulation prevents outer classes from accessing and changing a class’s fields and methods, as the variables and functions are integrated as a single unit with the class itself.
Proper encapsulation of a class is achieved by making all data members and function members private using access specifiers. This means that they can only be accessed within the class and cannot be accessed by other classes.
Furthermore, public methods called getters and setters are defined to permit external access to the instance variables. Getters are used to retrieve the values of instance variables, while setters are used to modify them. Using getters and setters, the class can enforce its data validation rules and guarantee that its internal state remains consistent.
What is the need for encapsulation in Java?
We saw what encapsulation means. Let us now look at why we need encapsulation:
1. Encapsulation gives complete control over the data members and methods within the class. It is a mechanism that hides a class’s implementation details from its users, helping to protect the data from unauthorised access and modification.
2. Standard IDES have built-in support for Getter and Setter methods, which can help speed up programming by making it easier to create and use these methods. Getters and setters are used to retrieve and update the value of a variable, protecting the data from accidental changes.
3. Encapsulation is the process of hiding a class’s internal data and methods from other classes. This makes the data more secure and prevents unauthorised access. It also makes the code more modular and easier to maintain. Encapsulation is a powerful tool that can improve the security, modularity, and maintainability of code.
4. Changes made to one part of the code can be implemented without causing any unintended consequences in other parts of the code. This allows for modifying one portion of the code without impacting other sections.
What do you mean by the term ‘Data Hiding’?
In Java, data hiding is the process of restricting access to a class’s data members by declaring them private. This prevents other classes from accessing the data members directly. Data hiding is a good practice because it helps to protect the data from being modified or accessed by unauthorised code.
Let us take a quick look at the access specifier with the help of an example:
A. Public: any class can access the method
class FirstCode { public int employees; public void display () { System.out.println ("Welocme to FirstCode"); System.out.println ("We have over " + employees + " employees."); } } public class Main { public static void main (String[]args) { FirstCode emp = new FirstCode (); emp.employees = 100; emp.display (); } }
Output:
Welocme to FirstCode
We have over 100 employees
B. Private: In the class in which the method is present, the class can access the method
class FirstCodeEmployee { private int salary; public int getSalary() {return salary;} public void setSalary(int salary) {this.salary = salary;} } public class Main { public static void main(String[] args) { FirstCodeEmployee emp = new FirstCodeEmployee(); emp.setSalary(100000); System.out.println("Employee salary is " + emp.getSalary()); } }
Output:
Employee salary is 100000
C. Protected: Only the same package, or subclasses in another package, can access the method
class human { protected String company; protected void display() { System.out.println("Hello, I am a " + company + " employee"); } } public class Employee extends human { public static void main(String[] args) { Employee emp = new Employee(); emp.company = "FirstCode"; emp.display(); } }
Output:
Hello, I am a FirstCode employee
D. Default: The method can be accessed only in the package where the process is declared
What are getter and setter methods?
Getter and setter methods are often used in object-oriented programming languages to provide a level of abstraction and encapsulation for data. Getter methods are used to retrieve the value of an attribute, while setter methods are used to change the value of an attribute. The implementation methods you use will determine whether or not an attribute can be read or updated.
For example, if you want an attribute called name to be read-only, you would implement the getter method but not the setter method. This would prevent other code from changing the value of the name attribute.
Getter and setter methods can also be used to validate data. For example, you could implement a setter method that checks to ensure the value being passed in is within a specific range. This would help to prevent errors from being introduced into your code. Generally, getter and setter methods are practical tools that can enhance the design and implementation of object-oriented code.
Here is an example:
public class FirstCodeEmployee { private String name; private String idNum; private int age; public int getAge() {return age;} public String getName() {return name;} public String getIdNum() {return idNum;} public void setAge(int newAge) {age = newAge;} public void setName(String newName) {name = newName;} public void setIdNum( String newId) {idNum = newId;} } class Employee { public static void main(String args[]) { FirstCodeEmployee emp = new FirstCodeEmployee(); emp.setName("Gopi Kiran"); emp.setAge(20); emp.setIdNum("12343ms"); System.out.print("Name : " + emp.getName() + " Age : " + emp.getAge()); } }
Output:
Name: Gopi Kiran Age: 20
Using getter and setter methods, we can also write-only and read-only classes. Let us look at an example for each:
1. Read-only class:
public class Main { private String Company="FirstCode"; public String getCompany() { return Company; } }
This class is read-only. You cannot change the variable “FirstCode,” as it is a private data type. If you attempt to change it, you will encounter a compile-time error.
2. Write only the class:
public class FirstCode { private String Company; public void setCompnay(String Company) { this.Company=Company; } }
In this class, you can only modify the value of the ‘Company’ data member, not retrieve it.
What are the differences between data hiding and encapsulation?
You may think that data hiding and encapsulation are the same. They are not. Let us examine their differences in a good old-fashioned table.
Data Hiding | Encapsulation |
Data hiding is related to data protection. | Encapsulation involves wrapping data into a single, cohesive module. |
It also helps to mask the complexities of the application. | It also helps to hide the application’s complexities. |
It also helps to mask the application’s complexities. | It emphasises concealing the system’s complexity. |
It is regarded as both a process and a method. | Encapsulation is a sub−process in the bigger process of data hiding. |
The data is always confidential and cannot be accessed. | The encapsulated data can be private or public, depending on the needs. |
What are the advantages of encapsulation?
Before we call it a day, let us take a brief moment to discuss the advantages and disadvantages of encapsulation:
1. Secures an object’s internal state by keeping it hidden from the outside world.
2. It makes code more modular and easier to maintain by allowing changes to be made without affecting other parts of the code.
3. Facilitates data abstraction, treating objects as a whole.
4. Facilitates the addition of new methods and fields without altering the existing code.
5. It helps hide an object’s inner workings, making it easier to change the implementation without affecting the rest of the code.
What are the disadvantages of implementing encapsulation?
Not everything is flawless; here are a couple of disadvantages you get when implementing encapsulation in Java.
1. Leads to more complexity, particularly if not used correctly.
2. Makes it more complicated to comprehend how the system functions.
3. Encapsulation can restrict the modification of the implementation.
Inheritance vs. abstraction vs. encapsulation
Inheritance, abstraction, and encapsulation are fundamental concepts in object-oriented programming, each serving a distinct purpose.
Here are the key differences between these concepts:
1. Inheritance:
a. Inheritance is a mechanism that allows a new class (subclass or derived class) to inherit properties and behaviors from an existing class (base class or superclass).
b. It promotes code reuse and establishes an “is-a” relationship between classes. For example, a “Car” class can be inherited from a “Vehicle” class because a car is a type of vehicle.
c. Subclasses can override or extend the behavior of the superclass methods.
d. Inheritance can lead to a hierarchical class structure with multiple levels of inheritance.
e. It can introduce tight coupling between classes if not used carefully, making it less flexible for changes.
2. Abstraction:
a. Abstraction is the process of simplifying complex reality by modeling classes based on their essential characteristics and hiding unnecessary details.
b. It focuses on creating abstract classes or interfaces that define a set of methods without specifying their implementation.
c. Abstraction helps manage complexity and improve code maintainability by separating what an object does from how it does it.
d. It allows you to work with high-level concepts and ignore low-level details.
e. Abstraction is achieved through abstract classes, interfaces, and method signatures.
3. Encapsulation
a. Encapsulation is a fundamental principle that involves bundling data (attributes) and methods (functions) that operate on that data into a single unit known as a class.
b. It restricts access to an object’s internal state and provides controlled access through methods (getters and setters) to maintain data integrity.
c. Encapsulation hides a class’s internal implementation details, making it easier to change the implementation without affecting other parts of the program that use the class.
d. It helps in achieving information hiding and protecting data from unauthorised access or modification.
e. Access modifiers like private, protected, and public are used to control the visibility of class members.
Understanding the accessibility of encapsulation
Below is a summary of the different access modifiers and the accessibility of the attributes or methods.
Modifier | Class | Package | Subclass | Other class |
No modifier | YES | YES | NO | NO |
Private | YES | NO | NO | NO |
Protected | YES | YES | YES | NO |
Public | YES | YES | YES | YES |
Conclusion
You have now learned about encapsulation, as we have discussed various topics, including its definition, the concept of data hiding, the need for encapsulation, and the use of getter and setter methods with examples. We have also explored the differences between data hiding and encapsulation, concluding with the advantages and disadvantages of encapsulation.