Object Oriented Programming With JavaUnit 1010 min read
Packages, Access Modifiers & Java Modularity
Unit 10 of Object Oriented Programming With Java covers Java’s package system, access modifiers (public, private, protected, default), and how they enforce encapsulation and modularity. Learn to create custom packages, import classes, and control visibility between classes—key for large-scale applications.
TAKEAWAYS:
- Packages organize Java classes hierarchically (e.g.,
java.utilfor utilities) and avoid naming conflicts using dot notation (com.example.app). - Access modifiers (
public,private,protected, default) restrict class/method visibility to control data hiding and reusability. importstatements bring external classes into scope, whilepackagedeclarations define namespace boundaries.- Default (package-private) access allows visibility only within the same package, enabling controlled collaboration between related classes.
- Poor access control leads to security risks (e.g., exposing sensitive data) or tight coupling; proper modifiers promote maintainability.
- Real-world use: Banks use packages to separate
Account,Transaction, andLoanlogic; eSewa isolates payment processing in its own package.
1. Why Use Packages?
Java packages serve three critical purposes:
- Namespace Management: Prevent naming collisions (e.g., two classes named
Userin different packages). - Access Control: Group related classes (e.g.,
java.util.ArrayListvs.java.sql.Array). - Modularity: Split large projects into logical units (e.g.,
com.example.uifor UI classes).
How Packages Work
- Declared at the top of a file with
package com.example.subpackage;. - Directory structure mirrors package names (e.g.,
com/example/subpackage/Class.java). - Default Package: Classes without a
packagedeclaration reside in an unnamed package (discouraged for production code).
Example: The java.util package contains ArrayList, HashMap, and Scanner, while java.io handles file operations.
2. Access Modifiers: Controlling Visibility
Access modifiers restrict how classes, methods, and fields can be accessed. Use them to enforce encapsulation.
| Modifier | Class | Package | Subclass | World |
|---|---|---|---|---|
public |
✅ | ✅ | ✅ | ✅ |
protected |
✅ | ✅ | ✅ | ❌ |
| Default | ✅ | ✅ | ❌ | ❌ |
private |
✅ | ❌ | ❌ | ❌ |
Key Rules
- Class-level modifiers: Only
publicor default (noprivate/protectedfor top-level classes). - Constructor modifiers: Control object creation (e.g.,
privateconstructors for singletons). - Method/field modifiers: Apply to members (e.g.,
privatefields hide implementation details).
Example: A BankAccount class hides its balance field as private but exposes deposit() and withdraw() as public.
package com.example.bank;
public class BankAccount {
private double balance; // Hidden from outside
public void deposit(double amount) {
if (amount > 0) balance += amount;
}
protected void transfer(BankAccount other, double amount) {
this.balance -= amount;
other.balance += amount;
}
}
Trace: If BankAccount is in com.example.bank and SavingsAccount extends it in com.example.savings:
deposit()is accessible worldwide (public).transfer()is accessible only in subclasses or the same package (protected).balanceis inaccessible outside the class (private).
3. Creating and Importing Packages
Step 1: Define a Package
Save Person.java in com/example/model/:
package com.example.model;
public class Person {
private String name;
public Person(String name) { this.name = name; }
public String getName() { return name; }
}
Step 2: Import and Use
In Main.java (same directory or another package):
import com.example.model.Person; // Import specific class
public class Main {
public static void main(String[] args) {
Person p = new Person("Rohan");
System.out.println(p.getName()); // Output: Rohan
}
}
Alternative: Import all classes from a package (not recommended for large packages):
import com.example.model.*; // Wildcard import
4. Real-World Applications
Example 1: eSewa’s Payment System
- Package Structure:
com.esewa/ ├── core/ // Payment logic (private to eSewa) │ └── Transaction.java ├── api/ // Public APIs for merchants │ └── PaymentGateway.java └── utils/ // Shared utilities - Access Modifiers:
Transactionfields (amount,status) areprivate.PaymentGatewayexposesprocessPayment()aspublicfor merchants.- Internal classes (e.g.,
FraudDetector) aredefault(package-private).
Example 2: Daraz’s Order Queue
- Package:
com.daraz.orderOrderclass (default access) manages orders within the package.OrderProcessor(public) handles external requests.
- Why? Prevents direct access to
Order’s internal state (e.g.,customerId), reducing bugs.
Example 3: Ncell’s Billing System
- Packages:
com.ncell.billing(private):BillGenerator,PaymentValidator.com.ncell.api(public):BillingAPI(exposesgenerateBill()).
- Access Control: Ensures only authorized classes (e.g.,
PaymentValidator) can modify billing data.
5. Common Pitfalls and Best Practices
| Pitfall | Solution |
|---|---|
Overusing public |
Restrict access to minimize side effects. |
| Circular dependencies | Refactor packages to reduce coupling. |
Wildcard imports (*.java) |
Explicitly import needed classes. |
| Exposing implementation details | Use interfaces (Unit 5) for contracts. |
Best Practice:
- Use
privatefor fields and helper methods. - Use
protectedfor subclass-specific logic. - Use
defaultfor package-private collaboration. - Use
publiconly for APIs or truly shared utilities.
6. Worked Example: Library Management System
Scenario: A library tracks books and members. Books should not be directly modified by members.
// Package: com.library.model
package com.library.model;
public class Book {
private String title;
private boolean isAvailable;
public Book(String title) {
this.title = title;
this.isAvailable = true;
}
public void borrow() {
if (isAvailable) isAvailable = false;
}
public void returnBook() {
isAvailable = true;
}
public boolean isAvailable() {
return isAvailable;
}
}
// Package: com.library.service
package com.library.service;
import com.library.model.Book;
public class Library {
private Book[] books = new Book[10];
public void addBook(Book book) {
for (int i = 0; i < books.length; i++) {
if (books[i] == null) {
books[i] = book;
break;
}
}
}
public Book findBook(String title) {
for (Book book : books) {
if (book != null && book.getTitle().equals(title)) {
return book;
}
}
return null;
}
}
Trace: A Member class (in com.library.user) can only interact with Library via public methods:
// Package: com.library.user
package com.library.user;
import com.library.service.Library;
public class Member {
public void borrowBook(Library library, String title) {
Book book = library.findBook(title);
if (book != null && book.isAvailable()) {
book.borrow(); // Calls private method indirectly
}
}
}
Visualization of Access:
classDiagram
class Book {
-String title
-boolean isAvailable
+borrow()
+returnBook()
}
class Library {
-Book[] books
+addBook(Book)
+findBook(String)
}
class Member {
+borrowBook(Library, String)
}
Library --> Book : "manages"
Member --> Library : "uses"
Member --> Book : "no direct access"7. Exam Tip
What Examiners Look For:
- Correct Package Declaration: Ensure the file path matches the package name (e.g.,
com/example/Class.java). - Proper Imports: Use
importfor external classes; avoid wildcard imports unless specified. - Access Modifier Usage:
- Fields/methods should use the most restrictive modifier possible.
- Top-level classes can only be
publicor default.
- Error Handling: Common mistakes include:
- Forgetting
packagedeclaration (default package). - Incorrect import paths (e.g.,
import com.example.Classwhen the class is incom.example.subpackage).
- Forgetting
- Diagrams: Draw package/class diagrams showing:
- Package boundaries (boxes).
- Access modifiers (arrows or labels).
- Relationships (e.g.,
AusesBfrom another package).
Sample Exam Question:
"Write a program to create two packages:
com.math(withCalculator) andcom.ui(withApp). ImportCalculatorinAppand demonstrate method calls. Use appropriate access modifiers."
Expected Answer Structure:
- Two directories:
com/math/andcom/ui/. Calculator.javawithpublicmethods (e.g.,add()).App.javawithimport com.math.Calculator;and usage.- Explanation of why
Calculatormethods arepublic.
8. Quick Revision Table
| Concept | Syntax/Example | Use Case |
|---|---|---|
| Package Declaration | package com.example; |
Organize classes hierarchically. |
| Import Statement | import com.example.Class; |
Access external classes. |
| Public Access | public class X { ... } |
API or shared utilities. |
| Private Access | private int value; |
Hide implementation details. |
| Protected Access | protected void helper() { ... } |
Subclass-specific logic. |
| Default Access | (No modifier) | Package-private collaboration. |
Final Note: Mastering packages and access modifiers is critical for writing scalable Java applications. Always ask:
- Who needs to access this?
- What’s the least permissive modifier that works?
- How can I reduce coupling between packages?
Based on the TU BITM syllabus for Object Oriented Programming With Java (IT234), unit 10.
Discussion
Loading…