Ch. 2 Object Oriented Concepts.
2.2 Access Specifiers
Introduction
In
Object-Oriented Programming, encapsulation is a core principle that
involves bundling the data (fields) and methods that operate on the data into a
single unit (the class). A key aspect of encapsulation is controlling how the
internal state of an object can be accessed or modified from outside the class.
This is where access specifiers (also known as
access modifiers) come into play.
Access specifiers in Java determine the visibility of a class, its
fields (variables), and its methods. They define the scope from which these
members can be accessed. By using them, you can protect your data from
unauthorized access or modification, enforce proper usage, and make your code
more robust and maintainable.
Java
provides four main access specifiers:
- public
- protected
- private
- default (or
package-private)
Explanation
The choice
of access specifier dictates who can "see"
and "use" a particular member of a class. This mechanism is vital for
implementing information hiding, allowing developers to expose only what
is necessary and hide the internal implementation details.
2.2.1 public
Introduction
The public
access specifier is the least restrictive. When a
class, field, or method is declared as public, it is accessible from anywhere in the program.
Explanation
Members
declared public have the widest scope. They can
be accessed:
- From
any other class in the same package.
- From
classes in different packages.
Typically, public is used for methods that define the public
interface of a class—the operations that other parts of the system are
intended to use. Fields are rarely made public directly, as this can break encapsulation.
// In file: MainApp.java
package finance;
import bank.BankAccount;
public class MainApp
{
public static void main(String[] args) {
// Create a
new BankAccount object
BankAccount myAccount = new BankAccount("12345", 1000.00);
// Display account info
myAccount.displayAccountInfo();
// Deposit money
myAccount.deposit(500.00);
// Check current balance using getter
System.out.println("Current balance: $" + myAccount.getBalance());
// Direct
access to public field (not recommended)
myAccount.accountNumber
= "98765";
System.out.println("Updated Account Number: " + myAccount.accountNumber);
}
}
2.2.2 protected
Introduction
The protected
access specifier allows members to be accessed:
- Within
the same package.
- By
subclasses (even if they are in different packages).
Explanation
protected is commonly used in inheritance
scenarios where subclasses require controlled access to parent class members.
Example
// File: bank/SavingsAccount.java
package bank;
/**
* Subclass representing a savings account
*/
public class SavingsAccount
extends BankAccount {
// Additional field for interest rate
private double interestRate;
// Constructor
public SavingsAccount(String
accNum, double initialBalance,
double rate) {
super(accNum, initialBalance); // Call
to parent constructor
this.interestRate
= rate;
}
// Method to apply interest to the balance
public void applyInterest()
{
double
interest = getBalance() * interestRate;
updateBalance(interest); // Accessing protected method from parent
}
}
2.2.3 private
Introduction
The private
access specifier is the most restrictive. Members
declared as private:
- Can
only be accessed within the same class.
- Are not
accessible by subclasses or other classes in the same package.
Explanation
private is commonly used for fields to
ensure strong encapsulation. Controlled access is provided via getters
and setters.
Example
// File: bank/BankAccount.java
package bank;
/**
* Class representing a basic bank account
*/
public class BankAccount
{
// Private fields (encapsulation)
private String accountNumber;
private double balance;
// Constructor to initialize account
public BankAccount(String
accNum, double initialBalance)
{
this.accountNumber
= accNum;
this.balance
= initialBalance;
}
// Public getter for account number
public String getAccountNumber()
{
return accountNumber;
}
// Public getter for balance
public double getBalance()
{
return
balance;
}
// Public method to deposit money
public void deposit(double amount) {
if (amount
> 0) {
balance +=
amount;
logTransaction("Deposit",
amount); // Log the deposit
} else {
System.out.println("Deposit
amount must be positive.");
}
}
// Private method to log transactions
private void logTransaction(String
type, double amount) {
System.out.println("Transaction: " + type + ", Amount: $"
+ amount);
}
}
2.2.4 default (package-private)
Introduction
When no
access specifier is provided, the member is said to
have default (package-private) access.
Explanation
Default
members:
- Can be
accessed by any class in the same package.
- Cannot
be accessed from outside the package.
Example
// File: bank/BankAccount.java
package bank;
/**
* A simple BankAccount
class demonstrating default access
*/
public class BankAccount
{
// Fields with default (package-private)
access
String accountNumber;
// Accessible within the same package
double
balance; // Accessible within the
same package
/**
* Internal method to apply some process on
the balance
* Default access (package-private)
*/
void internalProcess() {
balance *=
1.01; // Example: Apply 1% increase
}
}