What is encapsulation in java
we’ll cover below question which most asked in java interview:
1. What is encapsulation in java
2. how we can achieve encapsulation in java
3. Advantages of encapsulation in Java
1. What is encapsulation in java
Encapsulation in Java is one of the four fundamental Object-Oriented Programming (OOP) concepts, alongside inheritance, polymorphism, and abstraction. It refers to the bundling of data (attributes) and methods (functions) that operate on the data into a single unit, known as a class. The data is kept private, and access to it is controlled through public methods, which are also known as getter and setter methods.
Key principles of encapsulation in Java include:
1. Data Hiding: The internal details of an object, including its data, are hidden from the outside world. This is achieved by declaring the data members of a class as private.
2. Access Control: Access to the data is controlled through public methods (getters and setters). This allows the class to enforce rules and validations on how the data can be accessed or modified.
3. Data Integrity: Encapsulation helps maintain the integrity of the data by providing controlled access. Validations and checks can be added to setter methods to ensure that the data remains in a consistent and valid state.
Here’s a simple example to illustrate encapsulation in Java:
/*
* Author: Zameer Ali Mohil
* */
public class Student {
// Private data members
private String name;
private int age;
// Public getter method for 'name'
public String getName() {
return name;
}
// Public setter method for 'name'
public void setName(String name) {
// Validation can be added here
this.name = name;
}
// Public getter method for 'age'
public int getAge() {
return age;
}
// Public setter method for 'age'
public void setAge(int age) {
// Validation can be added here
if (age > 0) {
this.age = age;
} else {
System.out.println("Invalid age. Age must be greater than 0.");
}
}
}
In this example:
- The
Student
class encapsulates the data (name and age) by declaring them as private. - Public getter (
getName
,getAge
) and setter (setName
,setAge
) methods are provided to control access to the private data. - The getter methods allow read-only access to the data, and the setter methods enforce rules and validations before modifying the data.
Encapsulation helps in creating more maintainable and robust code by hiding the internal details of a class and providing a well-defined interface for interacting with the object. It also supports the principle of information hiding, which is a crucial aspect of object-oriented design.
how we can achieve encapsulation in java
1. Declare Data Members as Private: Designate the data members (fields or attributes) of a class as private. This ensures that they can only be accessed within the class.
public class MyClass {
private int myNumber;
private String myString;
}
2. Provide Public Getter and Setter Methods: Create public methods (getters and setters) to access and modify the private data. These methods allow controlled access to the encapsulated data.
public class MyClass {
private int myNumber;
private String myString;
public int getMyNumber() {
return myNumber;
}
public void setMyNumber(int myNumber) {
// Validation or additional logic can be added here
this.myNumber = myNumber;
}
public String getMyString() {
return myString;
}
public void setMyString(String myString) {
// Validation or additional logic can be added here
this.myString = myString;
}
}
3. Use Constructor Initialization: Initialize the private data members through constructors. This helps in ensuring that the object is in a valid state upon creation.
public class MyClass {
private int myNumber;
private String myString;
// Constructor
public MyClass(int myNumber, String myString) {
this.myNumber = myNumber;
this.myString = myString;
}
}
4. Apply Validation and Business Logic: Within the setter methods, incorporate validation and business logic to ensure that the data remains in a consistent and valid state.
public class MyClass {
private int myNumber;
private String myString;
public void setMyNumber(int myNumber) {
if (myNumber > 0) {
this.myNumber = myNumber;
} else {
System.out.println("Invalid value for myNumber. Must be greater than 0.");
}
}
public void setMyString(String myString) {
if (myString != null && !myString.isEmpty()) {
this.myString = myString;
} else {
System.out.println("Invalid value for myString. Cannot be null or empty.");
}
}
}
By following these practices, you encapsulate the internal details of a class and control access to its data. This promotes data integrity, enhances code maintainability, and allows for the implementation of necessary logic within the class itself. Encapsulation is a fundamental principle in object-oriented programming that contributes to the creation of modular and well-organized code.
Advantages of encapsulation in Java
Encapsulation in Java offers several advantages, contributing to the principles of object-oriented programming and the design of robust, maintainable, and secure code.
Here are some key advantages:
1. Data Hiding: Encapsulation hides the internal details of a class, including its data members, from the outside world. This helps prevent unauthorized access and manipulation of data, promoting security and preventing unintended interference.
public class BankAccount {
private double balance;
// Other methods and constructors...
// Getter method for balance
public double getBalance() {
return balance;
}
// Setter method for balance
public void setBalance(double balance) {
// Additional logic for validation, e.g., balance cannot be negative
if (balance >= 0) {
this.balance = balance;
} else {
System.out.println("Invalid balance. Cannot be negative.");
}
}
}
2. Controlled Access: Access to the internal state of an object is controlled through public methods (getters and setters). This allows for fine-grained control over how data is accessed, modified, and validated.
// Using the BankAccount class from the previous example
public class ClientCode {
public static void main(String[] args) {
BankAccount account = new BankAccount();
// Accessing and modifying balance through controlled methods
account.setBalance(1000.0);
double currentBalance = account.getBalance();
}
}
3. Flexibility and Maintenance: Encapsulation allows the internal implementation of a class to change without affecting the classes that use it. The external interface (public methods) can remain consistent while internal details evolve, making it easier to maintain and update code.
// Original class definition
public class OriginalClass {
private int data;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
// Modified class definition
public class ModifiedClass {
private String newData;
public String getNewData() {
return newData;
}
public void setNewData(String newData) {
this.newData = newData;
}
}
4. Code Organization: Encapsulation promotes a modular and organized code structure. Each class encapsulates its data and behavior, providing a well-defined interface to the rest of the system. This improves code readability and maintainability.
public class Student {
private String name;
private int age;
// Constructor, getters, setters, and other methods...
}
public class Course {
private String courseName;
private int courseId;
// Constructor, getters, setters, and other methods...
}
5. Data Integrity: By controlling access to data through methods, encapsulation enables the enforcement of rules, constraints, and validations on the data. This helps maintain the integrity of the data and ensures that it remains in a consistent state.
public class TemperatureSensor {
private double temperature;
public void setTemperature(double temperature) {
// Validation: Temperature should be within a specific range
if (temperature >= -50 && temperature <= 150) {
this.temperature = temperature;
} else {
System.out.println("Invalid temperature value.");
}
}
}
6. Encapsulation of Complex Operations: Complex operations can be encapsulated within methods, allowing the outside world to interact with the class through a simplified interface. This reduces complexity for the client code and promotes a higher level of abstraction.
public class ShoppingCart {
private List<Item> items;
// Other methods...
// Encapsulated complex operation
public void checkout() {
// Perform operations related to checkout
// Calculate total, apply discounts, update inventory, etc.
}
}
7. Facilitates Change Management: Encapsulation makes it easier to introduce changes to the internal implementation of a class. As long as the external interface remains consistent, changes can be made without affecting the classes that use the encapsulated class.
// Original class definition
public class OriginalClass {
private int data;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}
// Modified class definition
public class ModifiedClass {
private String newData;
public String getNewData() {
return newData;
}
public void setNewData(String newData) {
this.newData = newData;
}
// Additional methods or modified behavior...
}
8. Enhanced Security: By hiding implementation details, encapsulation contributes to security. Sensitive information or critical algorithms can be kept private, reducing the risk of unauthorized access and misuse.
public class SecureInformation {
private String secretKey;
// Getter method for secure information
public String getSecretKey() {
// Additional security checks and logic...
return secretKey;
}
}
9. Supports Reusability: Encapsulation supports the concept of encapsulated objects being reused in different contexts. Objects with well-defined interfaces can be reused in various parts of an application or even in different applications.
// Example of reusable class
public class Calculator {
// Methods for addition, subtraction, multiplication, etc.
}
10. Promotes Polymorphism: Encapsulation is a prerequisite for achieving polymorphism in object-oriented programming. Polymorphism allows objects of different types to be treated as objects of a common base type, enabling flexibility and extensibility.
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Drawing a square");
}
}
// Client code using polymorphism
public class DrawingApp {
public static void main(String[] args) {
Shape circle = new Circle();
Shape square = new Square();
circle.draw();
square.draw();
}
}
In summary, encapsulation is a key principle in Java that contributes to the creation of robust, secure, and maintainable code. It supports the principles of information hiding, data abstraction, and separation of concerns, facilitating the development of scalable and adaptable software systems.