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.
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
The package keyword tells the compiler to put the classes in this file inside packageName.
The package statement must be the very first line of code in your file.
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
CopyDownload
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
CopyTryDownload
import com.prowessapps.demo.GreetingService;
class PackageTest {
public static void main(String[] args) {
GreetingService service = new GreetingService();
service.greet("Ayan");
}
}
Output:
Welcome, Ayan!
Explanation
GreetingService belongs to com.prowessapps.demo.
The class is public, so code in another package may use it.
The import makes GreetingService available by its simple name.
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.
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
CopyTryDownload
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
Instead of importing the class, we type out its full identity: java.util.ArrayList.
This allows us to use ArrayList directly without needing an import statement at the top.
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
CopyTryDownload
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
import java.util.ArrayList; tells the compiler to look in the java.util package for the ArrayList class.
Because of this import, we can just use the short name ArrayList inside our code instead of its fully qualified name.
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
CopyTryDownload
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
The import static keyword is used to import static members (like PI and sqrt) directly into the file.
Because we imported them statically, we don't have to write Math.PI or Math.sqrt(25) anymore.
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.
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
CopyTryDownload
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
Java provides two different Date classes: one in java.util and one in java.sql.
We cannot import both Date classes at the top of the file without causing a naming conflict.
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 →
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.
Discussion
Ask questions, share suggestions, or discuss this lesson.