Java Tutorial » Chapter 28 — Packages

Chapter 28 — Java Packages

Organizing your classes and avoiding name collisions with namespaces.

1. Introduction to Packages

What is a Package?

A package in Java is a mechanism for organizing related classes and interfaces. Think of it as a folder or directory in a file system. It provides a namespace, which helps prevent naming conflicts. For example, you can have a class named `List` in your own package without it conflicting with Java's `java.util.List`.

Packages are essential for building large-scale, maintainable applications. They allow developers to group code logically, making it easier to find, use, and understand.

Key Benefits of Using Packages:

  • Reusability: Classes in packages can be easily reused in other programs.
  • Conflict Resolution: Two classes can have the same name as long as they are in different packages.
  • Organization: Related classes and interfaces are bundled together, making the codebase easier to navigate.
  • Access Control: Packages provide another layer of access control. Classes can be declared with no access modifier (package-private), making them accessible only to other classes within the same package.
2. Creating a Package

Declaring a Package

To place a class or interface into a package, you use the package statement at the very beginning of your Java source file. It must be the first line of code, before any imports or class definitions.

The standard naming convention for packages is to use a reversed Internet domain name to ensure uniqueness, followed by project and module names.

// File: src/com/example/vehicles/Car.java

// This line declares that the Car class belongs to the 'com.example.vehicles' package.
package com.example.vehicles;

public class Car {
    private String model;
    
    public Car(String model) {
        this.model = model;
    }
    
    public void drive() {
        System.out.println(model + " is driving.");
    }
}
3. The `import` Keyword

Using Classes from Other Packages

If you want to use a class from another package, you have two options:

  1. Use the fully qualified name of the class every time you use it. This can be verbose.
  2. Use the import statement to bring the class into your current file's namespace. This is the more common and convenient approach.
// File: src/Main.java

// Option 1: Using the fully qualified name (verbose)
public class MainVerbose {
    public static void main(String[] args) {
        // Must use the full package path every time
        com.example.vehicles.Car myCar = new com.example.vehicles.Car("Toyota");
        myCar.drive();
    }
}

// Option 2: Using the import statement (recommended)
import com.example.vehicles.Car; // Import the specific class
// import com.example.vehicles.*; // Or import all classes from the package

public class Main {
    public static void main(String[] args) {
        // Now we can use the class name directly
        Car myCar = new Car("Honda");
        myCar.drive();
        
        // Classes from java.lang (like String, System) are imported automatically
        String greeting = "Hello, World!";
        System.out.println(greeting);
    }
}
4. The Directory Structure of Packages

Mapping Packages to Folders

The package name directly corresponds to a directory structure on your file system. The Java compiler and JVM use this structure to locate your `.class` files. For a package named com.example.vehicles, the Car.class file must be located in a directory path like com/example/vehicles/.

A typical project structure might look like this:

MyJavaProject/
├── src/
│   ├── com/
│   │   └── example/
│   │       └── vehicles/
│   │           ├── Car.java
│   │           └── Truck.java
│   └── Main.java
└── out/ (or bin/)  <-- This is where the compiled .class files go
    ├── com/
    │   └── example/
    │       └── vehicles/
    │           ├── Car.class
    │           └── Truck.class
    └── Main.class

When you compile from the root of the `src` directory, the compiler will automatically create the corresponding directory structure in the output directory (`out` or `bin`). To run the `Main` class, you would navigate to the root of the output directory and execute:

# The command includes the full package name of the class to run
java Main
5. The CLASSPATH

Telling Java Where to Look

The CLASSPATH is an environment variable or a command-line argument that tells the Java Virtual Machine (JVM) and the Java compiler where to look for user-defined classes and packages.

Think of it as a list of directories and JAR files that Java searches when it needs to load a class. If a class is not found in the default locations, Java will look in each path specified in the CLASSPATH.

Important Note: In modern software development, you rarely set the CLASSPATH environment variable manually. Integrated Development Environments (IDEs) like IntelliJ and Eclipse, and build tools like Maven and Gradle, manage the classpath for you automatically. However, understanding the concept is still fundamental.

You can set the classpath temporarily when running a program using the -cp or -classpath flag:

# Tells java to look for classes in the 'out' directory
# The '.' represents the current directory
java -cp out Main

# If you had external libraries (JAR files), you would include them too
# (on Windows, the separator is a semicolon ;)
java -cp "out:lib/my-library.jar" Main
6. Practice & Challenge

Test Your Skills

  1. Create a package structure for your project: com.yourname.utils.
  2. Inside this package, create a class called StringHelper.
  3. Add a static method to StringHelper called public static String reverse(String s).
  4. Create another class called Main in the default package (no package statement).
  5. In the Main class, use the import statement to import your StringHelper class and use its reverse method.

🏆 Challenge: Application Structure

Design a package structure for a simple e-commerce application.

  • Create a main package: com.myapp.
  • Create sub-packages: com.myapp.model, com.myapp.service, and com.myapp.ui.
  • In the model package, create a Product class with fields like `id`, `name`, and `price`.
  • In the service package, create a ProductService class with a method public void displayProductDetails(Product p). This class will need to import the Product class from the model package.
  • In the ui package, create a MainApp class with a main method. This class will create a Product instance, create a ProductService instance, and call the service method to display the product's details.

// File: src/com/myapp/model/Product.java
package com.myapp.model;

public class Product {
    private String id;
    private String name;
    private double price;

    public Product(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
    
    // Getters
    public String getId() { return id; }
    public String getName() { return name; }
    public double getPrice() { return price; }
}

// File: src/com/myapp/service/ProductService.java
package com.myapp.service;

import com.myapp.model.Product; // Import the Product class

public class ProductService {
    public void displayProductDetails(Product p) {
        System.out.println("--- Product Details ---");
        System.out.println("ID: " + p.getId());
        System.out.println("Name: " + p.getName());
        System.out.printf("Price: $%.2f%n", p.getPrice());
        System.out.println("------------------------");
    }
}

// File: src/com/myapp/ui/MainApp.java
package com.myapp.ui;

import com.myapp.model.Product;
import com.myapp.service.ProductService;

public class MainApp {
    public static void main(String[] args) {
        // Create a product
        Product laptop = new Product("P101", "Super Laptop", 1299.99);

        // Create a service
        ProductService service = new ProductService();

        // Use the service to display product details
        service.displayProductDetails(laptop);
    }
}