Packages
1. What Is a Package?
-
A package is a group of related Java types such as:
-
Classes
-
Interfaces
-
Enums
-
Annotations
-
-
Packages provide:
-
Organization — keep related code together.
-
Namespace management — avoid naming conflicts.
-
Access control — control which classes can access each other.
-
Example:
package graphics;
Now the class belongs to the graphics package.
2. Why Use Packages?
Packages help with:
-
Organization: Group related classes together.
-
Naming conflicts: Different packages can contain classes with the same name.
graphics.Rectangle
java.awt.Rectangle
Both classes can exist because they belong to different packages.
-
Access control: Package-private members can be accessed by classes in the same package.
-
Discoverability: Makes it easier to find related functionality.
3. Creating a Package
Add a package statement at the beginning of the source file:
package graphics;
public class Circle {
// ...
}
Important:
-
The
packagestatement normally comes before imports and class declarations. -
Only one package can be declared in a source file.
-
If no package is declared, the class belongs to the unnamed package.
-
The unnamed package is generally avoided in larger applications.
4. Package Directory Structure
The directory structure normally follows the package name.
For:
package graphics;
the file would normally be:
graphics/
Circle.java
Rectangle.java
Point.java
For:
package com.example.app;
the structure is:
com/
└── example/
└── app/
├── Main.java
└── User.java
This allows Java tools to locate classes according to their package names.
5. Package Naming Convention
Package names are generally written in lowercase:
graphics
database
utils
com.example.app
For globally unique packages, Java commonly uses the reverse domain name:
example.com
becomes:
com.example
For example:
package com.example.myapp;
If a domain contains characters that aren't valid Java identifiers, an underscore can be used.
6. Using Classes from Another Package
Suppose we have:
package graphics;
public class Circle {
}
Another package can use it in three ways.
A. Fully Qualified Name
Use the complete package + class name:
graphics.Circle circle = new graphics.Circle();
No import is required.
B. Import a Specific Class
import graphics.Circle;
Circle circle = new Circle();
This is commonly preferred because it is clear which class you're using.
C. Import All Types
import graphics.*;
Circle circle = new Circle();
Rectangle rectangle = new Rectangle();
The * means:
all types directly inside graphics
It does not include subpackages.
7. Packages Are Not Hierarchical
This is an important point.
Having:
java.awt
java.awt.color
java.awt.font
does not mean importing:
import java.awt.*;
also imports:
java.awt.color
java.awt.font
You must import them separately:
import java.awt.*;
import java.awt.color.*;
Think of packages as separate namespaces, not folders that automatically include everything underneath them.
8. Handling Name Conflicts
Suppose two packages contain a class called Rectangle:
graphics.Rectangle
java.awt.Rectangle
If both are imported:
import graphics.Rectangle;
import java.awt.Rectangle;
Java cannot determine which Rectangle you mean.
You can solve this by using the fully qualified name:
graphics.Rectangle r1 = new graphics.Rectangle();
java.awt.Rectangle r2 = new java.awt.Rectangle();
9. Importing Nested Classes
You can also import nested types.
For example:
import graphics.Rectangle;
import graphics.Rectangle.*;
The first imports Rectangle.
The second imports accessible nested types declared inside Rectangle.
10. Static Imports
A static import allows you to use static fields and methods without writing the class name.
Without static import:
double result = Math.cos(Math.PI);
With:
import static java.lang.Math.*;
double result = cos(PI);
You can also import a specific static member:
import static java.lang.Math.PI;
double result = PI * 2;
Use static imports carefully because excessive use can make it unclear where a method or field comes from.
11. Package Access Control
Packages also work with Java's access modifiers.
A member with no access modifier is package-private:
class User {
String name;
}
Another class in the same package can access it:
User user = new User();
System.out.println(user.name);
But a class in another package cannot directly access name.
This makes packages useful for controlling which parts of your code are exposed.
12. Important Package Rules
| Rule | Meaning |
|---|---|
package |
Declares which package the type belongs to |
import |
Allows using another package's types by simple name |
package.* |
Imports types directly in that package |
package.* |
Does not import subpackages |
| Fully qualified name | Can be used without import |
| Static import | Imports static fields/methods directly |
| Same package | Package-private members are accessible |
| Different package | Package-private members aren't accessible |
| Directory structure | Normally follows package name |
13. Simple Example
Project:
src/
├── app/
│ └── Main.java
└── utils/
└── Calculator.java
Calculator.java:
package utils;
public class Calculator {
public static int add(int a, int b) {
return a + b;
}
}
Main.java:
package app;
import utils.Calculator;
public class Main {
public static void main(String[] args) {
int result = Calculator.add(10, 20);
System.out.println(result);
}
}
Output:
30
The important relationship is:
app.Main
|
| imports
↓
utils.Calculator
Quick Revision
Package
↓
Groups related classes/interfaces/enums
↓
Provides organization + namespace + access control
Most important syntax
package com.example.app;
import com.example.utils.Helper;
import com.example.utils.*;
import static java.lang.Math.*;
Remember
-
Package names are generally lowercase.
-
The
packagedeclaration comes before imports and class declarations. -
import package.*does not import subpackages. -
Packages are not hierarchical.
-
Fully qualified names can resolve naming conflicts.
-
Static imports allow direct use of static members.
-
Package-private members are accessible within the same package.