Packages and Namespaces in Java
Packages and Namespaces in Java
Packages first appeared in the Beginner tutorial as a way to organise related classes. Here, the focus widens to how packages function as Java's namespacing mechanism, the system that keeps two completely unrelated classes from colliding just because they happen to share a name.
What are Packages?
A package is a named, hierarchical grouping of related classes, interfaces, and sub-packages. Every class in Java belongs to exactly one package, even if you never write a package declaration yourself, in which case it silently belongs to what is called the default (unnamed) package.
Packages solve a problem that becomes unavoidable in any codebase of real size: naming collisions. Two different teams, or two different libraries, can each define a class named Logger or Order without conflict, because their full, qualified names, com.teamone.utils. Logger and com.teamtwo.core.Logger, are entirely distinct, even though the short class name is identical.
Creating and Importing Packages
A package declaration, using the package keyword, must be the very first line of a Java source file. The physical folder structure on disk must mirror the package name exactly; dots in the package name become folder separators.
// File location: com/store/inventory/Product.java
package com.store.inventory;
public class Product {
String name;
double price;
}
To use a class from another package, you import it. Java supports importing a single class, importing every public class in a package with a wildcard, and, since Java 9, importing static members directly so they can be used without qualifying them by class name.
package com.store.checkout;
import com.store.inventory.Product; // import a single class
// import com.store.inventory.*; // or import everything in the package
import static java.lang.Math.PI; // static import — use PI directly, no Math. prefix
public class Checkout {
public static void main(String[] args) {
Product p = new Product();
p.name = "Notebook";
System.out.println(PI); // 3.14159... — no need to write Math.PI
}
}
If you need to use two classes with the identical simple name from two different packages in the same file, you cannot import both; instead, you import one and refer to the other by its fully qualified name wherever it is used.
Built-in Java Packages Overview
The Java Standard Library itself is organised entirely as packages, and a handful of them come up constantly in everyday code.
Package | Contains | Common Classes |
java.lang | Core language classes, imported automatically in every file | String, Math, Object, System, Integer |
java.util | Utility classes and the Collections Framework | ArrayList, HashMap, Scanner, Optional |
java.io | Classes for input and output operations | File, FileReader, BufferedReader, InputStream |
java.util.function | Built-in functional interfaces for lambdas (Chapter 6) | Function, Predicate, Consumer, Supplier |
java.time | Modern date and time handling, introduced in Java 8 | LocalDate, LocalDateTime, Duration |
java.net | Networking classes for sockets and URLs | Socket, URL, HttpURLConnection |
java.lang is the one exception to the import rule: every class inside it, String, Math, Integer, Object, and others, is available in every Java file automatically, without ever writing an import statement, because the language considers it too fundamental to require explicit importing.
• Use reverse domain naming for your own top-level packages, such as com.companyname.projectname, to keep your package names globally distinct from anyone else's.
• Group related classes by feature or architectural layer (models, services, controllers, utils) rather than placing everything in one flat package.
• Avoid the default (unnamed) package for anything beyond a quick throwaway script; classes there cannot be properly imported by classes that do belong to a named package.
Quick Tip
If you ever see an error like 'class X is already defined' despite the two classes looking completely unrelated, check whether you have accidentally imported two classes with the same simple name from different packages, or left a class in the default package by mistake. Packages exist specifically to prevent this kind of collision, so it almost always traces back to a missing or incorrect package declaration somewhere.










