Access Modifiers#
Lecture 12#
Java Programming (4343203)
Diploma in ICT - Semester IV
Gujarat Technological University
Press Space for next page
layout: default#
Learning Objectives#
By the end of this lecture, you will be able to:
- ๐ Understand data encapsulation and information hiding principles
- ๐ก๏ธ Master all four access modifiers in Java
- ๐๏ธ Apply access control to protect class members
- ๐ Implement secure class design patterns
- ๐ฏ Choose appropriate access levels for different scenarios
- ๐ Practice with real-world encapsulation examples
Let's secure our code with access control! ๐๐ก๏ธ
layout: center#
What is Encapsulation?#
graph TD
A[Encapsulation] --> B[Data Hiding]
A --> C[Access Control]
A --> D[Security]
B --> E[Private Variables]
B --> F[Internal Implementation]
C --> G[Public Methods]
C --> H[Controlled Access]
D --> I[Data Validation]
D --> J[Unauthorized Access Prevention]
style A fill:#e3f2fd
style B fill:#e8f5e8
style C fill:#fff3e0
style D fill:#f3e5f5
๐๏ธ Encapsulation
- โข Bundling data and methods together
- โข Controlling access to internal details
- โข Protecting object state
- โข Enabling secure programming
๐ Benefits
- โข Data security and integrity
- โข Code maintainability
- โข Flexible implementation changes
- โข Better error handling
layout: default#
Access Modifiers Overview#
๐ก๏ธ Four Access Levels#
| Modifier | Symbol | Access Level |
|---|---|---|
| private | ๐ | Within same class only |
| default | ๐ฆ | Within same package |
| protected | ๐ | Package + subclasses |
| public | ๐ | Accessible everywhere |
๐ Visibility Scope#
public class AccessExample {
private int privateVar; // ๐ Class only
int defaultVar; // ๐ฆ Package
protected int protectedVar; // ๐ Package + subclasses
public int publicVar; // ๐ Everywhere
}
๐ฏ Access Control Matrix#
| Access Level | Same Class | Same Package | Subclass | Different Package |
|---|---|---|---|---|
| private | โ | โ | โ | โ |
| default | โ | โ | โ | โ |
| protected | โ | โ | โ | โ |
| public | โ | โ | โ | โ |
๐ฏ Key Principle: Provide the minimum access necessary for functionality!
layout: default#
Private Access Modifier#
๐ Most Restrictive Access#
- Accessible only within the same class
- Cannot be accessed from outside
- Used for internal implementation details
- Provides complete data hiding
- Foundation of encapsulation
๐ Basic Private Example#
public class BankAccount {
private double balance; // Hidden from outside
private String accountNumber; // Secret account details
private boolean isActive; // Internal state
// Private helper method
private boolean validateAmount(double amount) {
return amount > 0 && amount <= balance;
}
// Public method to access private data
public double getBalance() {
return balance;
}
}
๐ซ What Happens Without Private?#
// Without encapsulation (BAD)
public class UnsafeBankAccount {
public double balance; // Anyone can modify!
public String accountNumber; // Exposed sensitive data
public void withdraw(double amount) {
balance -= amount; // No validation!
}
}
// Dangerous usage
UnsafeBankAccount account = new UnsafeBankAccount();
account.balance = 1000000; // Illegal modification!
account.accountNumber = "123456"; // Security breach!
Problems:
- No data validation
- Security vulnerabilities
- Inconsistent state possible
- No control over modifications
โ ๏ธ Security Risk: Public data members expose internal implementation and create security holes!
layout: default#
Implementing Data Encapsulation#
๐๏ธ Complete Encapsulated Class#
public class Student {
// Private data members (hidden)
private String name;
private int rollNumber;
private double marks;
private boolean isActive;
// Constructor for initialization
public Student(String name, int rollNumber) {
this.name = name;
this.rollNumber = rollNumber;
this.marks = 0.0;
this.isActive = true;
}
// Getter methods (Accessors)
public String getName() {
return name;
}
public int getRollNumber() {
return rollNumber;
}
public double getMarks() {
return marks;
}
public boolean isActive() {
return isActive;
}
}
// Setter methods (Mutators) with validation
public void setName(String name) {
if (name != null && name.trim().length() > 0) {
this.name = name.trim();
} else {
System.out.println("Invalid name provided");
}
}
public void setMarks(double marks) {
if (marks >= 0 && marks <= 100) {
this.marks = marks;
} else {
System.out.println("Marks must be between 0 and 100");
}
}
public void setActive(boolean active) {
this.isActive = active;
}
// Business logic methods
public char getGrade() {
if (marks >= 90) return 'A';
else if (marks >= 80) return 'B';
else if (marks >= 70) return 'C';
else if (marks >= 60) return 'D';
else return 'F';
}
public void displayInfo() {
System.out.println("Student: " + name);
System.out.println("Roll Number: " + rollNumber);
System.out.println("Marks: " + marks);
System.out.println("Grade: " + getGrade());
System.out.println("Status: " + (isActive ? "Active" : "Inactive"));
}
}
layout: default#
Using Encapsulated Classes#
๐ฏ Safe Usage Example#
public class StudentDemo {
public static void main(String[] args) {
// Create student object
Student student = new Student("Alice Johnson", 101);
// Safe access through public methods
System.out.println("Name: " + student.getName());
System.out.println("Roll: " + student.getRollNumber());
// Validated data modification
student.setMarks(85.5);
student.setName("Alice M. Johnson");
// Display complete information
student.displayInfo();
// Attempt invalid operations
student.setMarks(150); // Will show error message
student.setMarks(-10); // Will show error message
student.setName(""); // Will show error message
// These would cause compilation errors:
// student.name = "Hacker"; // Error: private field
// student.rollNumber = 999; // Error: private field
// student.marks = 200; // Error: private field
}
}
๐ก๏ธ Benefits Demonstrated#
Data Validation:
student.setMarks(150); // Automatically validated
// Output: "Marks must be between 0 and 100"
Controlled Access:
// Can read but not directly modify
String name = student.getName(); // โ
Allowed
// student.name = "New Name"; // โ Compilation error
Flexible Implementation:
// Internal implementation can change without affecting users
public double getMarks() {
// Could add logging, caching, etc.
logAccess("Marks accessed for " + name);
return marks;
}
Data Integrity:
// Roll number cannot be changed after creation
// Only name and marks can be modified with validation
๐ Result: Secure, maintainable, and robust code!
layout: default#
Default (Package-Private) Access#
๐ฆ Package-Level Access#
- No access modifier specified
- Accessible within the same package
- Hidden from other packages
- Default access level in Java
- Useful for package-internal functionality
๐ Package Structure Example#
// File: com/university/Student.java
package com.university;
public class Student {
String studentId; // Package-private
String name; // Package-private
int semester; // Package-private
// Package-private method
void updateSemester(int newSemester) {
this.semester = newSemester;
}
public void displayInfo() {
System.out.println("Student: " + name);
System.out.println("ID: " + studentId);
System.out.println("Semester: " + semester);
}
}
๐๏ธ Package Access Usage#
// File: com/university/StudentManager.java
package com.university; // Same package
public class StudentManager {
public void processStudent() {
Student student = new Student();
// โ
Can access package-private members
student.studentId = "STU001";
student.name = "Bob Smith";
student.semester = 4;
// โ
Can call package-private methods
student.updateSemester(5);
student.displayInfo();
}
}
// File: com/admin/AdminPanel.java
package com.admin; // Different package
import com.university.Student;
public class AdminPanel {
public void manageStudent() {
Student student = new Student();
// โ Cannot access package-private members
// student.studentId = "ADM001"; // Compilation error
// student.name = "Admin"; // Compilation error
// student.updateSemester(1); // Compilation error
// โ
Can only access public methods
student.displayInfo();
}
}
layout: default#
Protected Access Modifier#
๐ Family-Level Access#
- Accessible in same package
- Accessible to subclasses (inheritance)
- Not accessible to unrelated classes
- Enables controlled inheritance
- Balance between private and public
๐งฌ Inheritance Hierarchy#
// Parent class
public class Vehicle {
protected String brand; // Subclasses can access
protected int maxSpeed; // Protected for inheritance
private String engineNumber; // Only Vehicle class
protected void startEngine() { // Subclasses can override
System.out.println("Engine started");
}
protected void displaySpecs() {
System.out.println("Brand: " + brand);
System.out.println("Max Speed: " + maxSpeed);
}
}
๐ Subclass Access#
// Child class
public class Car extends Vehicle {
private int numberOfDoors;
public Car(String brand, int maxSpeed, int doors) {
// โ
Can access protected members from parent
this.brand = brand;
this.maxSpeed = maxSpeed;
this.numberOfDoors = doors;
// โ Cannot access private members
// this.engineNumber = "ENG123"; // Compilation error
}
// โ
Can override protected methods
@Override
protected void startEngine() {
System.out.println("Car engine started with key");
super.startEngine(); // Call parent method
}
public void showCarDetails() {
// โ
Using protected method from parent
displaySpecs();
System.out.println("Doors: " + numberOfDoors);
}
}
// Usage example
public class VehicleDemo {
public static void main(String[] args) {
Car car = new Car("Toyota", 180, 4);
car.showCarDetails();
// โ Cannot access protected members directly
// car.brand = "Honda"; // Compilation error
// car.startEngine(); // Compilation error
}
}
layout: default#
Public Access Modifier#
๐ Universal Access#
- Accessible from anywhere
- No access restrictions
- Used for public APIs
- Classes, methods, and variables
- Maximum visibility
๐ Public Interface Design#
public class Calculator {
// Public constants
public static final double PI = 3.14159;
public static final double E = 2.71828;
// Public methods (API)
public double add(double a, double b) {
return a + b;
}
public double subtract(double a, double b) {
return a - b;
}
public double multiply(double a, double b) {
return a * b;
}
public double divide(double a, double b) {
if (b == 0) {
throw new IllegalArgumentException("Division by zero");
}
return a / b;
}
}
๐ฏ Global Usage#
// Can be used from any package, any class
import com.utilities.Calculator;
public class MathApplication {
public static void main(String[] args) {
Calculator calc = new Calculator();
// โ
All public methods accessible
double sum = calc.add(10, 5);
double difference = calc.subtract(10, 5);
double product = calc.multiply(10, 5);
double quotient = calc.divide(10, 5);
// โ
Public constants accessible
double circleArea = Calculator.PI * 5 * 5;
System.out.println("Sum: " + sum);
System.out.println("Difference: " + difference);
System.out.println("Product: " + product);
System.out.println("Quotient: " + quotient);
System.out.println("Circle Area: " + circleArea);
}
}
// Another class in different package
package com.games;
import com.utilities.Calculator;
public class GameScoring {
private Calculator calc = new Calculator();
public double calculateBonus(double base, double multiplier) {
return calc.multiply(base, multiplier); // โ
Public access
}
}
layout: default#
Real-World Example: Bank Account System#
๐ฆ Secure Banking Implementation#
public class BankAccount {
// Private - Critical data protection
private String accountNumber;
private double balance;
private String pinCode;
// Protected - For specialized account types
protected String accountType;
protected double interestRate;
// Package-private - Bank internal operations
String branchCode;
boolean isVerified;
// Public - Customer interface
public BankAccount(String accountNumber, String pinCode) {
this.accountNumber = accountNumber;
this.pinCode = pinCode;
this.balance = 0.0;
this.accountType = "SAVINGS";
this.interestRate = 0.04;
this.isVerified = false;
}
// Public methods for customer operations
public boolean authenticate(String pin) {
return this.pinCode.equals(pin);
}
public double getBalance(String pin) {
if (authenticate(pin)) {
return balance;
} else {
System.out.println("Authentication failed");
return -1;
}
}
}
public boolean deposit(double amount, String pin) {
if (!authenticate(pin)) {
System.out.println("Authentication failed");
return false;
}
if (amount > 0) {
balance += amount;
System.out.println("Deposited: โน" + amount);
return true;
} else {
System.out.println("Invalid amount");
return false;
}
}
public boolean withdraw(double amount, String pin) {
if (!authenticate(pin)) {
System.out.println("Authentication failed");
return false;
}
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: โน" + amount);
return true;
} else {
System.out.println("Invalid amount or insufficient funds");
return false;
}
}
// Protected method for subclasses
protected double calculateInterest() {
return balance * interestRate / 12; // Monthly interest
}
// Package-private for bank operations
void setVerificationStatus(boolean verified) {
this.isVerified = verified;
}
}
layout: default#
Specialized Account Types#
๐ณ Savings Account (Inheritance)#
public class SavingsAccount extends BankAccount {
private double minimumBalance;
public SavingsAccount(String accountNumber, String pinCode) {
super(accountNumber, pinCode);
this.minimumBalance = 1000.0;
this.accountType = "SAVINGS"; // โ
Protected access
this.interestRate = 0.04; // โ
Protected access
}
@Override
protected double calculateInterest() {
// โ
Can override protected method
return super.calculateInterest() * 1.2; // Bonus interest
}
@Override
public boolean withdraw(double amount, String pin) {
if (!authenticate(pin)) {
return false;
}
// Check minimum balance constraint
if (getBalance(pin) - amount >= minimumBalance) {
return super.withdraw(amount, pin);
} else {
System.out.println("Cannot withdraw. Minimum balance required: โน" + minimumBalance);
return false;
}
}
public double getMinimumBalance() {
return minimumBalance;
}
}
๐ง Usage and Security Demonstration#
public class BankingDemo {
public static void main(String[] args) {
SavingsAccount account = new SavingsAccount("SAV001", "1234");
// โ
Public interface usage
account.deposit(5000, "1234");
System.out.println("Balance: โน" + account.getBalance("1234"));
// โ
Specialized savings account behavior
account.withdraw(3500, "1234"); // Will check minimum balance
// โ
Account type specific method
System.out.println("Minimum balance: โน" + account.getMinimumBalance());
// โ Security - These would cause compilation errors:
// account.balance = 1000000; // Private
// account.pinCode = "0000"; // Private
// account.accountNumber = "HACK"; // Private
// โ These would also fail:
// account.calculateInterest(); // Protected
// account.setVerificationStatus(true); // Package-private
// Authentication protection
account.withdraw(1000, "wrong_pin"); // Will fail authentication
}
}
๐ Security Achieved:
- โข Critical data completely hidden
- โข All operations require authentication
- โข Business rules enforced automatically
- โข Inheritance enables specialization
layout: default#
Access Modifier Best Practices#
โ Design Guidelines#
Start with Most Restrictive:
- Begin with
privateby default - Only make
publicwhat’s absolutely necessary - Use
protectedfor inheritance hierarchies - Use package-private for related classes
Data Members:
- Almost always
private - Use getters/setters for controlled access
- Constants can be
public static final
Methods:
- Public for external interface
- Private for internal helpers
- Protected for overridable behavior
Classes:
- Public for external use
- Package-private for internal implementation
๐ฏ Common Patterns#
public class WellDesignedClass {
// Constants - public is acceptable
public static final String VERSION = "1.0";
// Critical data - always private
private String sensitiveData;
private double criticalValue;
// Configuration - package-private for testing
boolean debugMode;
// Extensible behavior - protected
protected void initialize() {
// Subclasses can override
}
// Public API - minimal and focused
public void performOperation() {
if (validate()) {
execute();
logOperation();
}
}
// Private helpers - internal implementation
private boolean validate() {
return sensitiveData != null;
}
private void execute() {
// Core logic
}
private void logOperation() {
// Logging implementation
}
}
๐ฏ Remember: Good encapsulation leads to secure, maintainable, and flexible code!
layout: default#
Hands-On Exercise: Employee Management System#
๐ ๏ธ Design Challenge#
Requirements:
- Create an Employee class with proper encapsulation
- Include employee ID, name, salary, and department
- Implement validation for all data
- Create specialized Manager subclass
- Demonstrate all access levels appropriately
public class Employee {
// TODO: Design with appropriate access modifiers
// - Employee ID (read-only after creation)
// - Name (changeable with validation)
// - Salary (private, controlled access)
// - Department (package access for HR)
// TODO: Constructor with validation
// TODO: Getters and setters with business rules
// TODO: Protected method for salary calculation
// TODO: Package method for HR operations
// TODO: Public methods for external interface
}
๐ฏ Expected Implementation#
public class Manager extends Employee {
// TODO: Additional manager-specific features
// - Team size
// - Bonus calculation
// - Override salary calculation
// TODO: Use protected inheritance appropriately
}
public class EmployeeDemo {
public static void main(String[] args) {
// TODO: Demonstrate:
// โ
Valid operations
// โ Security restrictions
// ๐ง Proper encapsulation usage
}
}
Success Criteria:
- All data properly encapsulated
- Validation in setters
- Appropriate access levels used
- Inheritance demonstrates protected usage
- Security violations prevented
- Clean public interface
layout: default#
Common Access Modifier Mistakes#
โ Making Everything Public
```java public class BadStudent { public String name; // No validation possible public int rollNumber; // Can be changed externally public double marks; // No business rules enforced } ``` Problem: No encapsulation, no data validation, security vulnerabilitiesโ Inconsistent Access Patterns
```java public class InconsistentClass { private String name; public String getName() { return name; } // Goodpublic double salary; // Bad - should be private
private void setSalary(double s) { salary = s; } // Bad - should be public
}
<strong>Problem:</strong> Confusing interface, breaks encapsulation principles
</div>
<div class="bg-yellow-50 p-4 rounded-lg">
<h4 class="font-bold text-yellow-700">โ Overusing Protected</h4>
```java
public class OverProtected {
protected String internalId; // Should probably be private
protected void helperMethod() {} // Internal logic, should be private
}
Problem: Exposes implementation details unnecessarily to subclasses
โ Correct Access Control
```java public class WellEncapsulated { private String name; // Data hidden public String getName() { return name; } // Controlled read access public void setName(String name) { // Validated write access if (name != null && !name.trim().isEmpty()) { this.name = name.trim(); } } } ```layout: center class: text-center#
Summary#
๐ What We Learned
- โข Encapsulation and data hiding principles
- โข Four access modifiers: private, default, protected, public
- โข Secure class design patterns
- โข Getters and setters implementation
- โข Real-world access control applications
- โข Best practices and common mistakes
๐ฏ Next Steps
- โข Understanding 'this', 'static', and 'final' keywords
- โข Advanced encapsulation techniques
- โข Constructor implementation
- โข Method and constructor overloading
- โข Object-oriented design patterns
Data security mastered! Your objects are now protected! ๐๐ก๏ธ
layout: center class: text-center#
Questions & Discussion#
โ
Any questions about access modifiers, encapsulation, or data security?
Next lecture: **Keywords - this, static, final**
Ready to explore powerful Java keywords! ๐

