Java Packages

Learn how to organize your Java classes into packages, avoid naming conflicts, and create well-structured, maintainable applications.

What is a Package?

A package in Java is a container (like a folder) that groups related classes, interfaces, and sub-packages together. It helps organize your code, prevents naming conflicts, and provides access control. Think of packages as organizing files into folders on your computer!

Imagine you have hundreds of Java files for a large project. Without packages, all files would be in one place – messy and confusing! Packages let you organize them logically: database classes in one package, user interface classes in another, utility classes in a third, and so on.

  • Organization: Group related classes together logically
  • Name Collision Prevention: Two classes can have the same name in different packages
  • Access Control: Provide additional level of encapsulation
  • Reusability: Package classes can be easily reused in other projects

Real-Life Analogy: A package is like a department in a company. The Sales department has its own employees (classes), the Engineering department has its own, and so on. Each department is organized and separate, but they all belong to the same company (project)!

Types of Packages in Java

1. Built-in Packages (Java API)

Pre-defined packages provided by Java. They contain thousands of classes that you can use directly without writing code from scratch.

Examples: java.lang (String, System, Math), java.util (ArrayList, Scanner, Date), java.io (File, InputStream, OutputStream)

2. User-defined Packages

Custom packages created by programmers to organize their own code. You define the package name and place your classes inside it.

Examples: com.company.project, org.myapp.database, in.mycompany.utilities

Package Naming Convention

Java follows specific naming conventions for packages to ensure uniqueness and clarity:

  • All Lowercase: Package names should be in lowercase letters only
  • Reverse Domain Name: Use reverse domain name format (com.company.project)
  • Dots as Separators: Use dots (.) to separate package levels
  • Meaningful Names: Use descriptive names that reflect the package content

Examples: com.google.android, org.apache.commons, in.crackease.utils, com.mycompany.project.database

Creating a Package

To create a package, use the package keyword as the first statement in your Java file (before any imports or class declarations).

Example: Creating a Simple Package

// File: Student.java
// First line must be package declaration
package com.school.students;

public class Student {
    String name;
    int rollNo;
    
    public Student(String name, int rollNo) {
        this.name = name;
        this.rollNo = rollNo;
    }
    
    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Roll No: " + rollNo);
    }
}

Explanation:

  • package com.school.students; declares the package name
  • This must be the first statement in the file (before imports and class)
  • The Student class now belongs to com.school.students package
  • File should be saved in folder structure: com/school/students/Student.java

Using Classes from Packages

To use classes from other packages, you need to import them using the import statement.

Example: Importing and Using Package Classes

// File: Main.java
// Import statement comes after package declaration (if any)
import com.school.students.Student;

public class Main {
    public static void main(String[] args) {
        // Using Student class from com.school.students package
        Student s1 = new Student("Alice", 101);
        s1.display();
        
        System.out.println();
        
        Student s2 = new Student("Bob", 102);
        s2.display();
    }
}
Output:
Name: Alice
Roll No: 101

Name: Bob
Roll No: 102

Explanation:

  • import com.school.students.Student; imports the Student class
  • After importing, you can use the class name directly
  • Without import, you'd need to use full name: com.school.students.Student
  • Import statements come after package declaration but before class declaration

Types of Import Statements

1. Specific Import

Import a specific class from a package. This is the most common and recommended approach as it clearly shows which classes you're using.

Syntax: import packageName.ClassName;
Example: import java.util.ArrayList;

2. Wildcard Import

Import all classes from a package using asterisk (*). Convenient but less clear about which classes are actually used.

Syntax: import packageName.*;
Example: import java.util.*;

3. Static Import

Import static members (methods, variables) directly so you can use them without class name prefix. Useful for constants and utility methods.

Syntax: import static packageName.ClassName.memberName;
Example: import static java.lang.Math.PI;

Import Examples

Let's see different ways to import and use classes from packages.

Example: Different Import Types

// Specific import - recommended
import java.util.ArrayList;
import java.util.Scanner;

// Wildcard import - imports all classes from java.io
import java.io.*;

// Static import - import static members
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

public class ImportExample {
    public static void main(String[] args) {
        // Using ArrayList (from specific import)
        ArrayList list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        System.out.println("Languages: " + list);
        
        // Using File (from wildcard import)
        File file = new File("test.txt");
        System.out.println("File name: " + file.getName());
        
        // Using static imports - no need for Math.PI or Math.sqrt
        double radius = 5.0;
        double area = PI * radius * radius;
        System.out.println("Circle Area: " + area);
        System.out.println("Square root of 16: " + sqrt(16));
    }
}
Output:
Languages: [Java, Python]
File name: test.txt
Circle Area: 78.53981633974483
Square root of 16: 4.0

Explanation:

  • Specific imports (ArrayList, Scanner) make it clear which classes are used
  • Wildcard import (java.io.*) imports all classes from java.io package
  • Static imports allow using PI and sqrt() without Math. prefix
  • Choose the import type based on your needs and coding standards

Using Classes Without Import

You can use classes from other packages without importing by using their fully qualified name (package name + class name).

Example: Fully Qualified Names

public class WithoutImport {
    public static void main(String[] args) {
        // Using fully qualified name - no import needed
        java.util.ArrayList list = new java.util.ArrayList<>();
        list.add("Hello");
        list.add("World");
        
        System.out.println("List: " + list);
        
        // Another example
        java.util.Date date = new java.util.Date();
        System.out.println("Current Date: " + date);
        
        // Using Scanner with full name
        java.util.Scanner sc = new java.util.Scanner(System.in);
        System.out.print("Enter your name: ");
        String name = sc.nextLine();
        System.out.println("Hello, " + name + "!");
        sc.close();
    }
}
Output:
List: [Hello, World]
Current Date: Wed Dec 03 10:30:45 IST 2025
Enter your name: John
Hello, John!

Explanation:

  • Using java.util.ArrayList instead of just ArrayList
  • No import statement needed when using fully qualified names
  • Useful when you have naming conflicts or use a class only once
  • Can make code verbose, so imports are generally preferred

Creating Sub-Packages

Packages can contain sub-packages, creating a hierarchical structure for better organization.

Example: Sub-Package Structure

// File: Database.java (in com.company.project.database package)
package com.company.project.database;

public class Database {
    public void connect() {
        System.out.println("Database connected!");
    }
}

// File: UserInterface.java (in com.company.project.ui package)
package com.company.project.ui;

public class UserInterface {
    public void display() {
        System.out.println("User interface displayed!");
    }
}

// File: Logger.java (in com.company.project.utils package)
package com.company.project.utils;

public class Logger {
    public void log(String message) {
        System.out.println("LOG: " + message);
    }
}

// File: Main.java
import com.company.project.database.Database;
import com.company.project.ui.UserInterface;
import com.company.project.utils.Logger;

public class Main {
    public static void main(String[] args) {
        Database db = new Database();
        UserInterface ui = new UserInterface();
        Logger logger = new Logger();
        
        logger.log("Application starting...");
        db.connect();
        ui.display();
        logger.log("Application running!");
    }
}
Output:
LOG: Application starting...
Database connected!
User interface displayed!
LOG: Application running!

Explanation:

  • Sub-packages create hierarchy: com.company.project.database, com.company.project.ui
  • Each sub-package is a separate unit with its own classes
  • Folder structure mirrors package structure: com/company/project/database/
  • This organization makes large projects manageable and logical

Built-in Java Packages

  • java.lang: Fundamental classes (String, Math, System, Integer) - imported by default
  • java.util: Utility classes (ArrayList, HashMap, Scanner, Date, Collections)
  • java.io: Input/Output classes (File, FileReader, FileWriter, InputStream, OutputStream)
  • java.net: Networking classes (URL, Socket, ServerSocket, HttpURLConnection)
  • java.sql: Database connectivity (Connection, Statement, ResultSet)
  • java.awt / javax.swing: GUI components (JFrame, JButton, JLabel)

Important Note: The java.lang package is automatically imported in every Java program, so you don't need to explicitly import classes like String, System, or Math!

Access Control with Packages

Packages work with access modifiers to control visibility of classes and members.

Example: Package-level Access

// File: Helper.java (in com.example.utils package)
package com.example.utils;

public class Helper {
    public void publicMethod() {
        System.out.println("Public method - accessible everywhere");
    }
    
    // Default (package-private) - accessible only within same package
    void packageMethod() {
        System.out.println("Package method - accessible in same package only");
    }
    
    private void privateMethod() {
        System.out.println("Private method - accessible only within this class");
    }
}

// File: Tester.java (in same package: com.example.utils)
package com.example.utils;

public class Tester {
    public static void main(String[] args) {
        Helper helper = new Helper();
        
        helper.publicMethod();    // ✓ Works - public
        helper.packageMethod();   // ✓ Works - same package
        // helper.privateMethod(); // ✗ Error - private
    }
}

// File: Main.java (in different package)
import com.example.utils.Helper;

public class Main {
    public static void main(String[] args) {
        Helper helper = new Helper();
        
        helper.publicMethod();    // ✓ Works - public
        // helper.packageMethod(); // ✗ Error - different package
        // helper.privateMethod(); // ✗ Error - private
    }
}

Explanation:

  • public members are accessible from any package
  • Default (no modifier) members are accessible only within the same package
  • private members are accessible only within the same class
  • Packages add an extra layer of access control and encapsulation

Advantages of Packages

  • Organization: Logically group related classes and interfaces together
  • Name Collision Avoidance: Two classes with same name can exist in different packages
  • Access Control: Provide additional level of protection through package-private access
  • Reusability: Packages can be easily reused across different projects
  • Maintainability: Easier to find and maintain code when organized in packages
  • Modularity: Create modular code with clear separation of concerns

Real-World Example: Java's own library uses packages extensively: java.util for utilities, java.io for input/output, java.sql for database. This organization makes it easy to find what you need!

Package Rules and Best Practices

  • Package Statement First: Package declaration must be the first statement (before imports)
  • One Package Per File: A Java file can belong to only one package
  • Folder Structure: Physical folder structure should match package names
  • Lowercase Names: Always use lowercase for package names
  • Meaningful Names: Use descriptive names that reflect the package purpose
  • Domain-Based Naming: Use reverse domain name (com.company.project) for uniqueness
  • No Java Keywords: Don't use Java keywords in package names

Best Practice: Organize your packages by functionality (com.company.database, com.company.ui) rather than by type (com.company.classes, com.company.interfaces). This makes the code more intuitive!

Key Points to Remember

  • Packages are containers that group related classes and interfaces
  • Use package keyword to declare a package (must be first statement)
  • Use import keyword to use classes from other packages
  • java.lang package is automatically imported in every program
  • Package names should be lowercase and follow reverse domain convention
  • Folder structure must match package structure
  • Packages provide organization, name collision prevention, and access control
  • Can use fully qualified names instead of imports when needed

Final Thought: Think of packages as organizing books in a library. Instead of throwing all books in one pile, you categorize them by subject (Science, History, Fiction). Packages do the same for your Java classes – making your code library organized and easy to navigate!