Java Packages – Built-in & User-defined Packages in Java

⏱️ 22 min read • Beginner Level • Lesson 53

Lesson 53 of 124 of Java Tutorial
You have completed this lesson

Completed on . You can revise this lesson or continue to the next topic.

Packages in Java group related classes, interfaces, enums, records, annotations, and sub-packages under meaningful namespaces.

Packages help organize large applications, reduce class-name conflicts, support access control, and make code easier to locate and maintain. In this lesson, you will create a package, compile it, import its classes, use fully qualified names, work with static imports, and understand package naming rules.


What is a Package in Java?

A package is a named namespace used to organize related Java types. A type's package becomes part of its complete identity. For example, java.util.Date and java.sql.Date are different classes even though both have the simple name Date.

Simple Meaning: A package works like a labeled folder and namespace that keeps related Java code organized.

Real-World Analogy

Imagine a company with separate departments such as Accounts, Human Resources, and Development. Each department groups people who perform related work. Java packages organize classes in a similar way.

Java Package Real-World Analogy
Packages help organize related classes into namespaces, similar to how departments group related people in a company.

Why Use Packages?

Better Organization

Place related classes in one logical module so developers can locate them quickly.

Avoid Name Conflicts

Two packages can contain classes with the same simple name without becoming the same type.

Access Control

Package boundaries participate in default and protected access rules.

Maintainability

A clear package structure makes applications easier to extend, test, and refactor.

Java Package Syntax

Declare a package with the package keyword. The declaration must be the first non-comment statement in the source file.

PackageSyntax.java
package packageName;

class ClassName {
    // fields, constructors, and methods
}

Explanation

  1. The package keyword tells the compiler to put the classes in this file inside packageName.
  2. The package statement must be the very first line of code in your file.
  3. All classes declared in this file will belong to packageName.
Important: Comments may appear before the package declaration, but an import, class declaration, or executable statement cannot appear before it.

Types of Java Packages

Package Type Meaning Example
Built-in package Provided by the Java platform. java.util
User-defined package Created by an application developer. com.prowessapps.demo
Unnamed package Used when no package declaration is present. Small beginner programs

Common Built-in Java Packages

Package Common Purpose Example Types
java.lang Core language support String, Math, System
java.util Collections and utilities ArrayList, Scanner, Random
java.io Stream-based input and output File, FileReader
java.nio.file Modern file-system operations Path, Files
java.time Date and time API LocalDate, LocalDateTime
java.net Networking URI, URL
Automatic Import: Java automatically makes the public types in java.lang available by simple name. Sub-packages of java.lang are not automatically imported.

Create a User-defined Package

The following example creates a reusable public class in com.prowessapps.demo and then uses it from another class.

Step 1: Create the Package Class

GreetingService.java
Copy Download
package com.prowessapps.demo;

public class GreetingService {
    public void greet(String name) {
        System.out.println("Welcome, " + name + "!");
    }
}

Step 2: Import and Use the Package Class

PackageTest.java
Copy Try Download
import com.prowessapps.demo.GreetingService;

class PackageTest {
    public static void main(String[] args) {
        GreetingService service = new GreetingService();
        service.greet("Ayan");
    }
}

Output:

Welcome, Ayan!

Explanation

  1. GreetingService belongs to com.prowessapps.demo.
  2. The class is public, so code in another package may use it.
  3. The import makes GreetingService available by its simple name.
  4. PackageTest creates the object and calls greet().

Compile and Run a Java Package

Run these commands from the project directory containing GreetingService.java and PackageTest.java. The -d option tells javac where to create the package directory structure for compiled classes.

Compile both files:

javac -d . GreetingService.java PackageTest.java

Run the class containing main():

java PackageTest
When main() is inside a named package: Run it with its fully qualified class name, such as java com.prowessapps.app.PackageTest.

Package Folder Structure

Java tools normally organize source and compiled files in directories that mirror the package components.

Source structure
src/
└── com/
    └── prowessapps/
        └── demo/
            └── GreetingService.java
Compiled structure
out/
└── com/
    └── prowessapps/
        └── demo/
            └── GreetingService.class

Fully Qualified Class Name

A fully qualified class name combines the package name and class name. It uniquely identifies a type and can be used without an import statement.

Simple class name: ArrayList

Fully qualified class name: java.util.ArrayList

FullyQualifiedNameExample.java
Copy Try Download
class FullyQualifiedNameExample {
    public static void main(String[] args) {
        java.util.ArrayList<String> languages =
                new java.util.ArrayList<>();

        languages.add("Java");
        languages.add("Python");

        System.out.println(languages);
    }
}

Output:

[Java, Python]

Explanation

  1. Instead of importing the class, we type out its full identity: java.util.ArrayList.
  2. This allows us to use ArrayList directly without needing an import statement at the top.
  3. This is extremely useful when resolving naming conflicts (e.g., if you have two classes with the same simple name).

Import Statement

An import declaration lets you refer to an accessible type by its simple name instead of repeating its fully qualified name.

ImportExample.java
Copy Try Download
import java.util.ArrayList;

class ImportExample {
    public static void main(String[] args) {
        ArrayList<String> languages = new ArrayList<>();

        languages.add("Java");
        languages.add("Python");

        System.out.println(languages);
    }
}

Output:

[Java, Python]

Explanation

  1. import java.util.ArrayList; tells the compiler to look in the java.util package for the ArrayList class.
  2. Because of this import, we can just use the short name ArrayList inside our code instead of its fully qualified name.
  3. This saves time and makes the code much cleaner to read.
Important: An import declaration does not copy a class into your source file. It allows an accessible type or static member to be referenced by a shorter name.

Types of Import Declarations

Import Type Example Purpose
Single-type import import java.util.Scanner; Makes one accessible type available by simple name.
Type-import-on-demand import java.util.*; Makes accessible types declared directly in one package available by simple name.
Single static import import static java.lang.Math.PI; Makes one accessible static member available by simple name.
Static-import-on-demand import static java.lang.Math.*; Makes accessible static members of one type available by simple name.

Static Import

Static import lets you use accessible static methods and constants without repeatedly writing the declaring class name.

StaticImportExample.java
Copy Try Download
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;

class StaticImportExample {
    public static void main(String[] args) {
        System.out.println(PI);
        System.out.println(sqrt(25));
    }
}

Output:

3.141592653589793
5.0

Explanation

  1. The import static keyword is used to import static members (like PI and sqrt) directly into the file.
  2. Because we imported them statically, we don't have to write Math.PI or Math.sqrt(25) anymore.
  3. We can just use their names directly (PI and sqrt), which makes mathematical calculations cleaner.
Best Practice: Use static imports selectively. Excessive static imports can make it difficult to identify which class originally defines a method or constant.

Unnamed Package

If a source file has no package declaration, its top-level types belong to an unnamed package, informally called the default package.

Best Practice: The unnamed package is convenient for tiny beginner examples, but named packages should be used for real applications. Code in named packages cannot import types from the unnamed package.

Java Package Naming Conventions

  • Write package components in lowercase.
  • Use valid Java identifiers; spaces and hyphens are not allowed.
  • Use a reverse-domain prefix to reduce global name conflicts.
  • Add descriptive components for the product, layer, or feature.
  • Avoid using names that begin with java or javax for application packages.
Package Name Assessment
com.prowessapps.java Recommended
com.prowessapps.util Recommended
MyPackage Avoid uppercase naming
java-package Invalid because of the hyphen

Packages and Access Control

Packages are part of Java's access-control system. Members with default access are available only inside the same package. Protected members are available in the same package and also through inheritance under Java's protected-access rules.

Java Package Access Control Matrix
The access-control matrix shows which members are accessible under different compilation and runtime scenarios.

Table Summary

Modifier Same Class Same Package Subclass in Another Package Unrelated Class in Another Package
public Yes Yes Yes Yes
protected Yes Yes Yes, through inheritance rules No
default Yes Yes No No
private Yes No No No

Tricky Cases

1. Can the package declaration appear after an import?

No. The package declaration must appear before import declarations and type declarations.

2. Does import java.util.*; include sub-packages?

No. It does not include types from sub-packages such as java.util.concurrent.

3. What if two packages contain a class with the same name?

Use the fully qualified class name for at least one of the conflicting types.

SameClassNameExample.java
Copy Try Download
class SameClassNameExample {
    public static void main(String[] args) {
        java.util.Date utilDate = new java.util.Date();
        java.sql.Date sqlDate =
                new java.sql.Date(System.currentTimeMillis());

        System.out.println(utilDate.getClass().getName());
        System.out.println(sqlDate.getClass().getName());
    }
}

Output:

java.util.Date
java.sql.Date

Explanation

  1. Java provides two different Date classes: one in java.util and one in java.sql.
  2. We cannot import both Date classes at the top of the file without causing a naming conflict.
  3. To solve this, we don't import them. Instead, we use their fully qualified names every time we create or use them so the compiler knows exactly which one we mean!

4. Is a sub-package automatically part of its parent package?

No. com.example and com.example.util are separate packages for imports and access control.

5. Can one source file contain multiple package declarations?

No. A compilation unit can have at most one package declaration.

Common Mistakes

  • Writing an import before the package declaration.
  • Using a package name that does not match the project's intended directory structure.
  • Assuming an on-demand import includes sub-packages.
  • Trying to import two classes with the same simple name.
  • Forgetting to make a top-level class public when it must be used from another package.
  • Overusing wildcard or static imports and reducing readability.
  • Placing production classes in the unnamed package.
  • Running a packaged main class without its fully qualified name.
Summary:
  • Packages give Java types organized namespaces.
  • The package declaration must appear before imports and type declarations.
  • Built-in packages come from Java; user-defined packages are created by developers.
  • An import lets accessible types or static members be used by shorter names.
  • On-demand imports do not include sub-packages.
  • A fully qualified name uniquely identifies a type.
  • Use lowercase reverse-domain package names in real projects.
  • Package boundaries influence default and protected access.

Interview Questions ⭐

A package is a named namespace that groups related Java types and helps organize code.

They improve organization, reduce naming conflicts, support access control, and help maintain large applications.

A built-in package is provided by the Java platform, such as java.util or java.time.

It is a package created by a developer for application-specific classes and interfaces.

Its accessible public types are automatically available by simple name in every compilation unit.

It is the package name followed by the class name, such as java.util.Scanner.

A source file without a package declaration places its top-level types in an unnamed package.

No. It allows an accessible type or member to be referred to by a simpler name in source code.

Yes. Their fully qualified names are different.

A normal import makes a type available by simple name, while a static import makes an accessible static member available by simple name.

No. Sub-packages must be referenced or imported separately.

It specifies the output directory and lets the compiler create the package directory structure for generated class files.

Use the package keyword followed by the package name and a semicolon, for example: package com.prowessapps.demo;.

The package declaration must be the first non-comment statement in a Java source file, before imports and type declarations.

No. A compilation unit can contain at most one package declaration.

A single-type import makes one accessible type available by its simple name, for example import java.util.Scanner;.

It makes accessible types declared directly in one package available by simple name, for example import java.util.*;.

A single static import makes one accessible static member available by simple name, for example import static java.lang.Math.PI;.

It makes accessible static members of one type available by simple name, for example import static java.lang.Math.*;.

Excessive static imports can make it difficult to identify the class that originally declares a method or constant.

Java tools and build systems normally organize source and compiled files in directories that mirror package components. Keeping them aligned prevents compilation and class-loading problems.

Use lowercase components and a reverse-domain prefix, such as com.prowessapps.util, followed by descriptive project or feature names.

No. Package components must be valid Java identifiers, so hyphens and spaces are not allowed.

No. For imports and access control, com.example and com.example.util are separate packages.

No. Types in the unnamed package cannot be imported by code in a named package.

The package name becomes part of the class's fully qualified name, so java.util.Date and java.sql.Date remain different types.

Use the fully qualified name for at least one of the classes, such as java.util.Date and java.sql.Date.

When no access modifier is written, the member or top-level type has default, or package-private, access and is available only within the same package.

A protected member is accessible throughout the same package and also to subclasses in other packages under Java's protected-access rules.

No. A top-level class can be public or package-private. Private and protected are allowed for nested classes, not top-level classes.

Yes. Packages can organize classes, interfaces, enums, records, annotation interfaces, and other named Java types.

No. Accessible public types in java.lang are automatically available without an explicit import.

No. Imports are a source-code convenience for resolving names and do not provide a runtime performance improvement.

The compiler reports an error. An import does not bypass public, protected, package-private, or private access rules.

Run it using its fully qualified class name and a classpath whose root contains the package directory, for example java com.prowessapps.app.Main.

A package is a Java namespace declared in source code. A folder is a file-system directory commonly used by tools to represent the package structure.

Uppercase letters can form valid identifiers, but Java naming conventions strongly recommend lowercase package names.

Using the simple name becomes ambiguous. Do not single-import both; use a fully qualified name for at least one class.

Yes. Accessible types in the same package can be referenced by simple name without an import declaration.

It reduces the chance of package-name collisions by beginning with a domain name controlled by the organization, written in reverse order.

Next step: Master how Java controls access across packages →

Continue to Java Access Modifiers →

Test your understanding with a quick quiz



🚀 Quick Knowledge Check

Topic: Packages | Language: Java

Question 1 of 50
Q1. What should a real application generally avoid?
Q2. How many package declarations can one compilation unit have?
Q3. Which naming style is recommended for packages?
Q4. What package contains Path and Files?
Q5. Can a package contain interfaces and enums?
Q6. Which statement imports the PI static field?
Q7. What is the difference between a package and a directory?
Q8. Can a top-level class be protected?
Q9. Which statement about protected members is correct?
Q10. Which class normally needs an explicit import or fully qualified name?
Q11. Which package is automatically available by simple name?
Q12. Which keyword declares a package?
Q13. What does import java.util.* make available?
Q14. Which statement about import performance is correct?
Q15. Which command correctly runs a main class in package com.app?
Q16. Which is a built-in Java package?
Q17. Which is a valid user-defined package name?
Q18. Which package name is invalid?
Q19. Can an import appear before the package declaration?
Q20. Why should static imports be limited?
Q21. Does an import bypass access modifiers?
Q22. What does an import declaration do?
Q23. Can a top-level class be private?
Q24. What happens if an imported type is not accessible?
Q25. Can a class use another accessible class from the same package without importing it?
Q26. What package contains ArrayList?
Q27. What does package-private access mean?
Q28. Which modifier allows access everywhere when the declaration itself is accessible?
Q29. Are com.example and com.example.util the same package?
Q30. What does javac -d . MyClass.java do?
Q31. What is the fully qualified name of Scanner?
Q32. If no package declaration is written, where does the class belong?
Q33. Which class is automatically available without import?
Q34. Which package declaration is syntactically correct?
Q35. Does import java.util.* import java.util.concurrent types?
Q36. Where should a package declaration appear?
Q37. What is a package in Java?
Q38. What package contains LocalDate?
Q39. What is the output?
class Test {
    public static void main(String[] args) {
        java.util.ArrayList<String> list = new java.util.ArrayList<>();
        list.add("Java");
        System.out.println(list);
    }
}
Q40. Can two packages contain a class named Date?
Q41. Is import java.lang.* required?
Q42. Can code in a named package import a type from the unnamed package?
Q43. Which is a type-import-on-demand declaration?
Q44. Can comments appear before a package declaration?
Q45. What is the output?
import static java.lang.Math.sqrt;

class Test {
    public static void main(String[] args) {
        System.out.println(sqrt(25));
    }
}
Q46. What is a likely result of importing two classes with the same simple name?
Q47. Which statement imports only Scanner?
Q48. Which declaration makes accessible Math static members available by simple name?
Q49. What does reverse-domain naming help prevent?
Q50. How can java.util.Date and java.sql.Date be used in the same file?

Great job! Continue learning Java OOP step by step.

Discussion

Ask questions, share suggestions, or discuss this lesson.

Please login or create an account to join the discussion and save your learning activity.

Loading comments...

Have you completed this lesson?

Mark this lesson as completed to track your learning progress. To keep track across devices, please login and save your learning progress.

Not completed yet.