[!NOTE] As your application grows from 5 files to 5,000 files, throwing everything into a single folder becomes chaos. Java uses a strict "Package" system mapped directly to your operating system's folders.
Packages (Folders)
A package is simply a directory structure. To avoid naming colllisions globally (where two companies both create a DatabaseConnection class), Java conventionally uses reversed internet domain names as the root package structure.
If your company domain is google.com, your project structure might look like this:
src/
└── com/
└── google/
└── auth/
└── LoginManager.java
└── database/
└── QueryExecutor.java
At the absolute very top line of LoginManager.java, you MUST declare the package it lives inside:
// Line 1: Package declaration
package com.google.auth;
// Now we import classes from OTHER packages
import java.util.Scanner;
import com.google.database.QueryExecutor;
public class LoginManager { ... }
Access Modifiers Matrix
We briefly touched on public and private. But there are actually 4 distinct levels of visibility in Java. Understanding this matrix is critical for interview questions.
| Modifier | Access inside same Class | Access inside same Package | Access from a Subclass (Child) | Access from the World everywhere |
|---|---|---|---|---|
public |
✅ | ✅ | ✅ | ✅ |
protected |
✅ | ✅ | ✅ | ❌ |
| (default) | ✅ | ✅ | ❌ | ❌ |
private |
✅ | ❌ | ❌ | ❌ |
The "Default" (Package-Private) Mystery
If you write a variable without ANY keyword (e.g., String token;), it defaults to Package-Private.
Any other class living in the exact same folder (package) can see and modify that variable. But if a class in a different folder tries to access it, the compiler throws an error.
When to use what?
- Use
privatefor 99% of your instance variables to enforce Encapsulation. - Use
publicfor classes, constructors, and methods you want the whole application to use (like a.saveData()method). - Use
protectedfor variables that you want to hide from developers, but allow inheriting Child classes to manipulate directly for performance logic.
Packages Communicate Ownership
Packages are not just folders. They tell readers where a class belongs in the system. A class in com.quizmaker.auth should probably deal with authentication. A class in com.quizmaker.payment should probably deal with payment behavior.
Typical Backend Package Layout
src/main/java/com/example/app/
controller/
service/
repository/
model/
config/
This structure keeps web entry points, business logic, database access, data models, and configuration separate. The exact names can vary, but the idea is to avoid one messy package full of unrelated classes.
Access Modifier Design
- Use
privatefor fields and helper methods that only the class should use. - Use package-private when classes in the same package collaborate internally.
- Use
protectedsparingly for inheritance extension points. - Use
publiconly for APIs other code should depend on.
Common Mistakes
- Making everything public because it feels easier at first.
- Using packages only as random folders instead of meaningful boundaries.
- Creating circular dependencies between packages.
- Relying heavily on
protectedfields instead of protected or public methods.
Mini Practice
Design a package layout for a quiz application with users, quizzes, attempts, and payments. Decide which classes should be public and which helpers should stay package-private or private.
Practice Lab: Organize a Mini App
Plan packages and visibility before writing many classes.
- Design packages for
user,quiz,payment, andcommon. - Place model classes in the most relevant package.
- Decide which classes should be public.
- Make helper methods private when only one class needs them.
- Use package-private for helpers shared only inside one package.
Goal: Treat packages and access modifiers as design boundaries.
Revision Checkpoint
- Package: Organizes classes and communicates ownership.
private: Same class only.- Package-private: Same package only.
protected: Same package plus subclasses.public: Accessible broadly; use intentionally.
Before the quiz: Choose the narrowest access modifier that still allows required usage.